facebook/docusaurus · error · Error

useTabsContext() must be used within a Tabs component

Error message

useTabsContext() must be used within a Tabs component

What it means

useTabs() reads the TabsContext created by <Tabs>/TabsProvider. React.useContext returns null when the hook is called from a component that is not a descendant of a TabsProvider, and the guard throws 'useTabsContext() must be used within a Tabs component'. This is the standard React 'missing provider' failure.

Source

Thrown at packages/docusaurus-theme-common/src/utils/tabsUtils.tsx:297

    },
    [setQueryString, setStorageValue, tabValues],
  );

  return {
    selectedValue,
    selectValue,
    tabValues,
    lazy: props.lazy ?? false,
    block: props.block ?? false,
  };
}

const TabsContext = createContext<TabsContextValue | null>(null);

export function useTabs(): TabsContextValue {
  const contextValue = React.useContext(TabsContext);
  if (!contextValue) {
    throw new Error('useTabsContext() must be used within a Tabs component');
  }
  return contextValue;
}

export function TabsProvider(props: {
  children: ReactNode;
  value: TabsContextValue;
}): ReactNode {
  return (
    <TabsContext.Provider value={props.value}>
      {props.children}
    </TabsContext.Provider>
  );
}

View on GitHub (pinned to 3f483e80e3)

Solutions

  1. Move the component calling useTabs() to be a descendant of <Tabs>.
  2. In tests, render the consumer inside <TabsProvider value={...}> or a real <Tabs>.
  3. Pass the needed value via props instead of context if the component must live outside the Tabs tree.

Example fix

// before
function TabLabel() {
  const {selectedValue} = useTabs(); // rendered outside <Tabs>
  return <b>{selectedValue}</b>;
}
<TabLabel />
<Tabs>...</Tabs>
// after
<Tabs>
  <TabLabel />
</Tabs>
Defensive patterns

Strategy: type-guard

Try / catch

// In a custom hook used in non-Tabs contexts
import {useTabs} from '@docusaurus/theme-common/internal';

function useTabsOptional() {
  try {
    return useTabs();
  } catch {
    return null; // caller falls back to props
  }
}

Prevention

When it happens

Trigger: Call useTabs() in a component rendered outside <Tabs>; use it in a unit test without wrapping in TabsProvider; lift a TabItem-child component above the <Tabs> boundary during refactor.

Common situations: Extracting an inline child into a standalone component placed at the wrong level; RTL/Jest tests of a tab-aware component without the provider; reordering JSX so the consumer renders before/above <Tabs>.

Related errors


AI-assisted analysis of facebook/docusaurus@3f483e80e3 (2026-08-12). Data as JSON: /api/errors/d5ec668a5e971c13. Report an issue: GitHub.