facebook/docusaurus · error · ReactContextError
Hook is called outside the <DocSidebarItemsExpandedStateProv
Error message
Hook is called outside the <DocSidebarItemsExpandedStateProvider>.
What it means
Thrown by useDocSidebarItemsExpandedState() when the context value equals the EmptyContext sentinel, meaning no <DocSidebarItemsExpandedStateProvider> ancestor rendered. This provider tracks which sidebar category index is expanded; it is mounted inside the docs sidebar. ReactContextError produces 'Hook useDocSidebarItemsExpandedState is called outside the <DocSidebarItemsExpandedStateProvider>.'. The sentinel (EmptyContext) rather than null is the missing-provider signal here.
Source
Thrown at packages/docusaurus-plugin-content-docs/src/client/docSidebarItemsExpandedState.tsx:52
*/
export function DocSidebarItemsExpandedStateProvider({
children,
}: {
children: ReactNode;
}): ReactNode {
const [expandedItem, setExpandedItem] = useState<number | null>(null);
const contextValue = useMemo(
() => ({expandedItem, setExpandedItem}),
[expandedItem],
);
return <Context.Provider value={contextValue}>{children}</Context.Provider>;
}
export function useDocSidebarItemsExpandedState(): ContextValue {
const value = useContext(Context);
if (value === EmptyContext) {
throw new ReactContextError('DocSidebarItemsExpandedStateProvider');
}
return value;
}
View on GitHub (pinned to 3f483e80e3)
Solutions
- Keep useDocSidebarItemsExpandedState() calls within components rendered under <DocSidebarItemsExpandedStateProvider> (i.e. inside the docs sidebar).
- If you swizzled the sidebar layout, ensure DocSidebarItemsExpandedStateProvider still wraps the children.
- In isolated tests, wrap the component in <DocSidebarItemsExpandedStateProvider>.
- Prefer passing expandedItem/setExpandedItem via props if the component is also used outside the sidebar.
Example fix
// before: hook called in a component not under the provider
function CategoryToggle() {
const { expandedItem, setExpandedItem } = useDocSidebarItemsExpandedState();
}
// after: render within the provider-wrapped sidebar tree
<DocSidebarItemsExpandedStateProvider>
<CategoryToggle />
</DocSidebarItemsExpandedStateProvider> Defensive patterns
Strategy: validation
Validate before calling
// There is no public 'useContext' export for this internal context,
// so the practical guard is structural: only render the component inside
// <DocSidebarItemsExpandedStateProvider>.
function useIsInSidebarTree() {
// Approximate: the sidebar expanded-state provider only exists under the
// docs sidebar layout. Route must be a docs route.
const route = useRouteContext();
return route?.plugin?.name === 'docusaurus-plugin-content-docs';
}
// if (!useIsInSidebarTree()) return null; Prevention
- Keep expanded-state hooks inside the docs sidebar subtree.
- When swizzling the sidebar, preserve DocSidebarItemsExpandedStateProvider around children.
- In tests, wrap components in <DocSidebarItemsExpandedStateProvider>.
When it happens
Trigger: Calling useDocSidebarItemsExpandedState() in a component outside the docs sidebar tree; swizzling the sidebar and forgetting to keep the provider; rendering a sidebar item component in isolation (test/storybook) without the provider.
Common situations: Swizzling SidebarItem to add expand/collapse behavior and using the hook at the wrong level; reusing a sidebar subcomponent in a non-sidebar layout; a custom theme that reorganizes the docs layout and drops the provider.
Related errors
- Hook is called outside the <DocsSidebarProvider>.
- Hook is called outside the <DocProvider>.
- Hook is called outside the <DocsPreferredVersionContextProvi
- Hook is called outside the <DocsVersionProvider>.
- Hook is called outside the <BlogPostProvider>.
AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12).
Data as JSON: /api/errors/2d94fc8ba976faf1.
Report an issue: GitHub.