marmelab/react-admin · error

useEditContext must be used inside an EditContextProvider

Error message

useEditContext must be used inside an EditContextProvider

What it means

useEditContext is a hook that reads the EditContext (the controller state of an <Edit> view: record, save, isPending, error, etc.). react-admin throws this error when the hook is called with no EditContextProvider above it in the React tree, because there is nothing to return. It is a guard against using the hook outside an edit page context.

Source

Thrown at packages/ra-core/src/controller/edit/useEditContext.tsx:22

import { EditContext } from './EditContext';
import { EditControllerResult } from './useEditController';

/**
 * Hook to read the edit controller props from the EditContext.
 *
 * Used within a <EditContextProvider> (e.g. as a descendent of <Edit>).
 *
 * @returns {EditControllerResult} edit controller props
 *
 * @see useEditController for how it is filled
 */
export const useEditContext = <
    RecordType extends RaRecord = any,
    ErrorType = Error,
>(): EditControllerResult<RecordType, ErrorType> => {
    const context = useContext(EditContext);
    if (!context) {
        throw new Error(
            'useEditContext must be used inside an EditContextProvider'
        );
    }
    return context as EditControllerResult<RecordType, ErrorType>;
};

View on GitHub (pinned to 051f511bb0)

Solutions

  1. Wrap the consuming component in <EditContextProvider value={controllerProps}> or render it inside an <Edit> view
  2. If the component must work in multiple views, use the generic useRecordContext/useSaveContext hooks or the useEditController hook instead
  3. In tests/stories, wrap the component with a provider supplying a fake EditControllerResult

Example fix

// before
const MyToolbar = () => {
  const { record } = useEditContext();
  ...
};
// after
const MyToolbar = () => {
  const { record } = useEditContext();
  ...
};
// usage
<Edit>
  <MyToolbar />
</Edit>
// or standalone:
const controller = useEditController({ resource: 'posts', id: 1 });
<EditContextProvider value={controller}><MyToolbar /></EditContextProvider>
Defensive patterns

Strategy: validation

Validate before calling

import { EditContext } from 'ra-core';
import { useContext } from 'react';
const ensureEditContext = () => {
  const ctx = useContext(EditContext);
  if (!ctx) throw new Error('Missing EditContextProvider');
  return ctx;
};

Type guard

const hasEditContext = (c: unknown): c is EditControllerResult =>
  c != null && typeof c === 'object' && 'record' in c && 'save' in c;

Try / catch

// Cannot try/catch hook calls in the same component; guard at a parent level
const EditGate = ({ children }) => {
  const ctx = useContext(EditContext);
  if (!ctx) return <EditFallback />;
  return children;
};

Prevention

When it happens

Trigger: Calling useEditContext() in a component rendered outside <Edit> (e.g. in a custom <List> page, a standalone page, or a storybook render without wrapping the component in <EditContextProvider>), or rendering a component that internally calls the hook without the provider.

Common situations: Reusing an edit-page child component (custom toolbar, tab) on a create page or list page; rendering the component in isolation in tests/Storybook; upgrading react-admin where a component previously received props and now relies on context.

Related errors


AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30). Data as JSON: /api/errors/abcc0cc3de2600dd. Report an issue: GitHub.