streamich/react-use · error · Error

useStateContext must be used inside a StateProvider.

Error message

useStateContext must be used inside a StateProvider.

What it means

Thrown by the hook returned from createStateContext when it is called outside a matching <StateProvider>. The factory creates a context defaulted to undefined; useStateContext reads it with useContext and, when the value is null or undefined (== null), concludes no provider is supplying the [value, setValue] tuple and throws. It is the state (useState) analogue of the reducer-context guard and has the same structural cause.

Source

Thrown at src/factory/createStateContext.ts:22

  const context =
    createContext<[T, React.Dispatch<React.SetStateAction<T>>] | undefined>(undefined);
  const providerFactory = (props, children) => createElement(context.Provider, props, children);

  const StateProvider = ({
    children,
    initialValue,
  }: {
    children?: React.ReactNode;
    initialValue?: T;
  }) => {
    const state = useState<T>(initialValue !== undefined ? initialValue : defaultInitialValue);
    return providerFactory({ value: state }, children);
  };

  const useStateContext = () => {
    const state = useContext(context);
    if (state == null) {
      throw new Error(`useStateContext must be used inside a StateProvider.`);
    }
    return state;
  };

  return [useStateContext, StateProvider, context] as const;
};

export default createStateContext;

View on GitHub (pinned to fbe99c6327)

Solutions

  1. Wrap the consuming subtree in the <StateProvider> returned from the same createStateContext call.
  2. Call createStateContext once at module scope, export both useStateContext and StateProvider together, and import them as a pair — never mix members from two factory calls.
  3. In tests/SSR, mount the consumer inside the provider rather than bare.
  4. Lift the provider above any portal or Suspense boundary that contains the consumer.

Example fix

// before
const [useStateContext, StateProvider] = createStateContext(0);
function Child() {
  const [count, setCount] = useStateContext(); // throws: no provider above
  return <p>{count}</p>;
}
export default function App() {
  return <Child/>;
}

// after
export default function App() {
  return (
    <StateProvider>
      <Child/>
    </StateProvider>
  );
}
Defensive patterns

Strategy: validation

Validate before calling

// Structural: ensure consumers render inside their <StateProvider>.
export const [useStateContext, StateProvider] = createStateContext<T>(defaultValue);

// Always compose like this:
<StateProvider>
  <ConsumesState/>
</StateProvider>

Type guard

// Narrow a value to the [value, setter] tuple expected from the provider.
const isStateTuple = <T>(
  v: unknown
): v is [T, React.Dispatch<React.SetStateAction<T>>] =>
  Array.isArray(v) && v.length === 2 && typeof v[1] === 'function';

// As with error 0, the practical guard is the provider in the tree, not a
// pre-call probe (the hook throws on undefined context).

Try / catch

class ProviderBoundary extends React.Component<
  { children: React.ReactNode; fallback: React.ReactNode },
  { hasError: boolean }
> {
  state = { hasError: false };
  static getDerivedStateFromError() { return { hasError: true }; }
  render() {
    return this.state.hasError ? this.props.fallback : this.props.children;
  }
}
// <ProviderBoundary fallback={<p>StateProvider missing</p>}><Consumes/></ProviderBoundary>

Prevention

When it happens

Trigger: Calling the useStateContext hook (first element of the tuple returned by createStateContext(defaultInitialValue)) in a component that is not a descendant of the corresponding <StateProvider>. Also triggered by using a hook from one createStateContext call inside a provider from a different call (each call creates a distinct context).

Common situations: Missing <StateProvider> wrapper around the consuming component; portal/lazy subtrees that escape the provider; isolated unit/SSR renders mounting the consumer without the provider; exporting the hook and Provider from separate factory calls and mixing them.

Related errors


AI-assisted analysis of streamich/react-use@fbe99c6327 (2026-08-12). Data as JSON: /api/errors/97e9f40da0d72ca0. Report an issue: GitHub.