{"record":{"id":"61d310274a87f917","repo":"marmelab/react-admin","slug":"usesimpleformiterator-must-be-used-inside-a-simple","errorCode":null,"errorMessage":"useSimpleFormIterator must be used inside a SimpleFormIterator","messagePattern":"useSimpleFormIterator must be used inside a SimpleFormIterator","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ra-core/src/controller/input/useSimpleFormIterator.ts","lineNumber":13,"sourceCode":"import { useContext } from 'react';\nimport { SimpleFormIteratorContext } from './SimpleFormIteratorContext';\n\n/**\n * A hook that provides access to a SimpleFormIterator data (the total number of items) and mutators (add, reorder and remove).\n * Useful to create custom array input iterators.\n * @see {SimpleFormIterator}\n * @see {ArrayInput}\n */\nexport const useSimpleFormIterator = () => {\n    const context = useContext(SimpleFormIteratorContext);\n    if (!context) {\n        throw new Error(\n            'useSimpleFormIterator must be used inside a SimpleFormIterator'\n        );\n    }\n    return context;\n};\n","sourceCodeStart":1,"sourceCodeEnd":19,"githubUrl":"https://github.com/marmelab/react-admin/blob/051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0/packages/ra-core/src/controller/input/useSimpleFormIterator.ts#L1-L19","documentation":"useSimpleFormIterator exposes the iteration API (add, remove, move, total fields) stored in SimpleFormIteratorContext, which only <SimpleFormIterator> provides. When called outside that context react-admin throws instead of returning undefined methods that would crash later.","triggerScenarios":"Calling useSimpleFormIterator in a custom input rendered outside <SimpleFormIterator> — e.g. directly under <ArrayInput>, inside a plain form, or in a button placed as a sibling rather than a child of the iterator.","commonSituations":"Writing a custom 'delete row' button and placing it outside the <SimpleFormIterator> children; moving the component after a refactor so it is no longer a descendant of the iterator; using the hook inside custom ArrayInput variants that do not use SimpleFormIterator.","solutions":["Move the calling component inside <SimpleFormIterator> children so it is below the context provider.","If you control row rendering, use SimpleFormIteratorItem / the row props (fields, remove) passed by the iterator instead of the hook.","For fully custom iterators, provide SimpleFormIteratorContext yourself with add/remove/move functions."],"exampleFix":"// before\n<ArrayInput source=\"items\">\n  <RemoveItemButton /> {/* throws: outside iterator */}\n  <SimpleFormIterator />\n</ArrayInput>\n// after\n<ArrayInput source=\"items\">\n  <SimpleFormIterator>\n    <RemoveItemButton /> {/* inside iterator context */}\n  </SimpleFormIterator>\n</ArrayInput>","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const isInsideSimpleFormIterator = (ctx: SimpleFormIteratorContextValue | null): ctx is SimpleFormIteratorContextValue =>\n  ctx != null && typeof ctx.add === 'function' && typeof ctx.remove === 'function';","tryCatchPattern":"try {\n  const { remove } = useSimpleFormIterator();\n} catch (e) {\n  if (e.message.includes('useSimpleFormIterator must be used inside')) {\n    // fallback: disable the control instead of crashing\n    return null;\n  }\n  throw e;\n}","preventionTips":["Place custom row controls (delete/reorder buttons) inside <SimpleFormIterator> children only.","Document context requirements on custom components built on iterator hooks.","Avoid rendering iterator-context consumers through state lifting into other branches of the tree.","Prefer the row props provided by the iterator over raw hooks when possible."],"tags":["react-admin","react-context","simple-form-iterator","hooks"],"backgroundTag":"hook-outside-provider","analyzedSha":"051f511bb0afb5ea565c2d3728bf4dab0a6fa5e0","analyzedAt":"2026-08-30T02:28:14.926Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}