react-navigation/react-navigation · error · Error

useFrameSize must be used within a FrameSizeProvider

Error message

useFrameSize must be used within a FrameSizeProvider

What it means

useFrameSize reads FrameContext to subscribe to frame (window/screen) size updates with a selector. The context is provided by FrameSizeProvider, which react-navigation sets up internally around navigator content; when absent, the hook has nothing to subscribe to and throws.

Source

Thrown at packages/elements/src/useFrameSize.tsx:35

type FrameContextType = {
  getCurrent: () => Frame;
  subscribe: (listener: Listener) => RemoveListener;
  subscribeThrottled: (listener: Listener) => RemoveListener;
};

const FrameContext = getNamedContext<FrameContextType | undefined>(
  'FrameContext',
  undefined
);

export function useFrameSize<T>(
  selector: (frame: Frame) => T,
  throttle?: boolean
): T {
  const context = React.use(FrameContext);

  if (context == null) {
    throw new Error('useFrameSize must be used within a FrameSizeProvider');
  }

  const value = useSyncExternalStoreWithSelector(
    throttle ? context.subscribeThrottled : context.subscribe,
    context.getCurrent,
    context.getCurrent,
    selector
  );

  return value;
}

type FrameSizeProviderProps = {
  initialFrame: Frame;
  render: (props: {
    ref: React.RefObject<React.ComponentRef<typeof View> | null>;
    onLayout: (event: LayoutChangeEvent) => void;
  }) => React.ReactNode;

View on GitHub (pinned to ab1319d6bb)

Solutions

  1. Render the consuming component inside a navigator (screen content) so FrameSizeProvider from react-navigation wraps it
  2. Align @react-navigation/elements with your navigator package versions so the internal FrameSizeProvider is present
  3. Wrap standalone usage manually in FrameSizeProvider with an explicit frame value
  4. For tests/stories, wrap the component in a FrameSizeProvider mock provider

Example fix

// before
// App root — outside any navigator
const tabHeight = useFrameSize(f => f.height); // throws

// after
function ScreenContent() { // rendered inside a navigator screen
  const tabHeight = useFrameSize(f => f.height);
  return <View />;
}
Defensive patterns

Strategy: fallback

Validate before calling

import { FrameContext } from '@react-navigation/elements';
const ctx = React.useContext(FrameContext);
if (ctx == null) console.warn('useFrameSize used outside FrameSizeProvider');

Type guard

function useFrameSizeSafe<T>(selector: (f: Frame) => T, fallback: T): T {
  const ctx = React.useContext(FrameContext);
  return ctx == null ? fallback : selector(ctx.getCurrent());
}

Try / catch

Not applicable — context hooks throw on render. Use a provider or guarded context read:
const width = React.useContext(FrameContext)?.getCurrent().width ?? fallbackWidth;

Prevention

When it happens

Trigger: Calling useFrameSize() outside the provider tree — e.g. in the app root above NavigationContainer, in a modal/portal rendered outside the navigator, or in a component used before the internal FrameSizeProvider mounts (older/mismatched package versions where the provider isn't installed).

Common situations: Using useFrameSize-derived helpers (tabBarHeight, header defaults) in custom components placed outside navigator screens; version mismatch between @react-navigation/elements and navigator packages so the provider isn't rendered; tests rendering hooks without navigator wrappers.

Related errors


AI-assisted analysis of react-navigation/react-navigation@ab1319d6bb (2026-08-31). Data as JSON: /api/errors/ae711e3d11a76aa0. Report an issue: GitHub.