marmelab/react-admin · error · Error
useSimpleFormIterator must be used inside a SimpleFormIterat
Error message
useSimpleFormIterator must be used inside a SimpleFormIterator
What it means
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.
Source
Thrown at packages/ra-core/src/controller/input/useSimpleFormIterator.ts:13
import { useContext } from 'react';
import { SimpleFormIteratorContext } from './SimpleFormIteratorContext';
/**
* A hook that provides access to a SimpleFormIterator data (the total number of items) and mutators (add, reorder and remove).
* Useful to create custom array input iterators.
* @see {SimpleFormIterator}
* @see {ArrayInput}
*/
export const useSimpleFormIterator = () => {
const context = useContext(SimpleFormIteratorContext);
if (!context) {
throw new Error(
'useSimpleFormIterator must be used inside a SimpleFormIterator'
);
}
return context;
};
View on GitHub (pinned to 051f511bb0)
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.
Example fix
// before
<ArrayInput source="items">
<RemoveItemButton /> {/* throws: outside iterator */}
<SimpleFormIterator />
</ArrayInput>
// after
<ArrayInput source="items">
<SimpleFormIterator>
<RemoveItemButton /> {/* inside iterator context */}
</SimpleFormIterator>
</ArrayInput> Defensive patterns
Strategy: type-guard
Type guard
const isInsideSimpleFormIterator = (ctx: SimpleFormIteratorContextValue | null): ctx is SimpleFormIteratorContextValue => ctx != null && typeof ctx.add === 'function' && typeof ctx.remove === 'function';
Try / catch
try {
const { remove } = useSimpleFormIterator();
} catch (e) {
if (e.message.includes('useSimpleFormIterator must be used inside')) {
// fallback: disable the control instead of crashing
return null;
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- useSimpleFormIteratorItem must be used inside a SimpleFormIt
- useArrayInput must be used inside an ArrayInputContextProvid
- useEditContext must be used inside an EditContextProvider
- useReferenceFieldContext must be used inside a ReferenceFiel
- useCreateSuggestionContext must be used inside a CreateSugge
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/61d310274a87f917.
Report an issue: GitHub.