{"record":{"id":"565eea92226dc450","repo":"marmelab/react-admin","slug":"deletebutton-components-should-be-used-inside-a","errorCode":null,"errorMessage":"<DeleteButton> components should be used inside a <Resource> component or provided the resource prop.","messagePattern":"<DeleteButton> components should be used inside a <Resource> component or provided the resource prop\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/ra-ui-materialui/src/button/DeleteButton.tsx","lineNumber":70,"sourceCode":" *     return <Edit actions={<EditActions />} {...props} />;\n * };\n */\nexport const DeleteButton = React.forwardRef(function DeleteButton<\n    RecordType extends RaRecord = any,\n>(\n    inProps: DeleteButtonProps<RecordType>,\n    ref: React.ForwardedRef<HTMLButtonElement>\n) {\n    const props = useThemeProps({\n        name: PREFIX,\n        props: inProps,\n    });\n\n    const { mutationMode, ...rest } = props;\n    const record = useRecordContext(props);\n    const resource = useResourceContext(props);\n    if (!resource) {\n        throw new Error(\n            '<DeleteButton> components should be used inside a <Resource> component or provided the resource prop.'\n        );\n    }\n    const { canAccess, isPending } = useCanAccess({\n        action: 'delete',\n        resource,\n        record,\n    });\n    const saveContext = useSaveContext(props);\n    if (!record || record.id == null || !canAccess || isPending) {\n        return null;\n    }\n\n    const finalMutationMode = mutationMode\n        ? mutationMode\n        : saveContext?.mutationMode\n          ? saveContext.mutationMode\n          : 'undoable';","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-ui-materialui/src/button/DeleteButton.tsx#L52-L88","documentation":"DeleteButton deletes the current record of a resource; it needs both a record (from RecordContext or props) and a resource name (from ResourceContext or props). When the resource cannot be resolved, the delete mutation and access-control check cannot be built, so it throws.","triggerScenarios":"Rendering <DeleteButton /> outside a record/list context without resource (and typically record) props; using it in a custom row renderer that dropped the resource context; mounting it app-level for 'delete current item' logic.","commonSituations":"Custom action toolbars outside Edit/Show/List views; refactors moving DeleteButton into shared components; test setups rendering the button alone.","solutions":["Pass resource (and record if no context): <DeleteButton resource=\"posts\" record={post} />","Wrap in <ResourceContextProvider> / <RecordContextProvider> or render inside Edit/Show/List views","Forward resource from parent components when abstracting the button"],"exampleFix":"// before\nexport const MyActions = () => <DeleteButton />;\n\n// after\nexport const MyActions = ({ resource, record }) => (\n  <DeleteButton resource={resource} record={record} />\n);","handlingStrategy":"type-guard","validationCode":"if (!resource || !record) return null; // DeleteButton needs both","typeGuard":"const canDelete = (p: { resource?: string; record?: Record }): p is { resource: string; record: Record } =>\n  typeof p.resource === 'string' && p.resource.length > 0 && p.record != null;","tryCatchPattern":"try {\n  return <DeleteButton {...props} />;\n} catch (e) {\n  if (e.message.includes('DeleteButton')) {\n    return <DeleteButton resource={fallbackResource} record={fallbackRecord} {...props} />;\n  }\n  throw e;\n}","preventionTips":["Keep DeleteButton inside Edit/Show/List or record-context scope","Pass resource and record explicitly in extracted/shared components","Wrap custom rows with RecordContextProvider + ResourceContextProvider","Add tests for shared action components rendered outside standard views"],"tags":["react-admin","resource-context","missing-prop","button"],"backgroundTag":"missing-resource-context","analyzedSha":"051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0","analyzedAt":"2026-08-30T02:28:14.926Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}