{"record":{"id":"8810b2311f690457","repo":"ionic-team/ionic-framework","slug":"an-ionic-router-is-required-for-ionroutercontext","errorCode":null,"errorMessage":"An Ionic Router is required for IonRouterContext","messagePattern":"An Ionic Router is required for IonRouterContext","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/react/src/components/IonRouterContext.tsx","lineNumber":24,"sourceCode":"\nexport interface IonRouterContextState {\n  routeInfo: RouteInfo;\n  push: (\n    pathname: string,\n    routerDirection?: RouterDirection,\n    routeAction?: RouteAction,\n    routerOptions?: RouterOptions,\n    animationBuilder?: AnimationBuilder\n  ) => void;\n  back: (animationBuilder?: AnimationBuilder) => void;\n  canGoBack: () => boolean;\n  nativeBack: () => void;\n}\n\nexport const IonRouterContext = React.createContext<IonRouterContextState>({\n  routeInfo: undefined as any, // TODO(FW-2959): type\n  push: () => {\n    throw new Error('An Ionic Router is required for IonRouterContext');\n  },\n  back: () => {\n    throw new Error('An Ionic Router is required for IonRouterContext');\n  },\n  canGoBack: () => {\n    throw new Error('An Ionic Router is required for IonRouterContext');\n  },\n  nativeBack: () => {\n    throw new Error('An Ionic Router is required for IonRouterContext');\n  },\n});\n\n/**\n * A hook for more direct control over routing in an Ionic React application. Allows you to pass additional meta-data to the router before the call to the native router.\n */\nexport function useIonRouter(): UseIonRouterResult {\n  const context = useContext(IonRouterContext);\n","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/ionic-team/ionic-framework/blob/625f9c38ad8c5db8a6c12df5c1622a36da90f9e3/packages/react/src/components/IonRouterContext.tsx#L6-L42","documentation":"This is the default `push` function on the IonRouterContext created by `React.createContext`. It exists only as a placeholder so that TypeScript is satisfied and so that calling the hook outside a provider fails loudly instead of silently no-op'ing. It throws when `useIonRouter().push(...)` is invoked but no `<IonReactRouter>` ancestor supplied a real context value.","triggerScenarios":"Calling `const router = useIonRouter(); router.push('/path')` in a React component that is rendered outside the `<IonReactRouter>` provider tree, so `useContext(IonRouterContext)` returns the default object whose `push` throws.","commonSituations":"Using `useIonRouter()` in a layout, modal, portal, or dev-tools panel rendered outside `<IonReactRouter>`; testing a component in isolation without wrapping it in `<IonReactRouter>`; conditional rendering that mounts the component before the router.","solutions":["Ensure the component using `useIonRouter()` is rendered inside `<IonReactRouter>` (which provides the real IonRouterContext value).","In tests, wrap the component under test with `<IonReactRouter><Route>...</Route></IonReactRouter>` (or the app's full router setup).","Move portals/modals that need routing inside the router tree, or pass router actions down via props instead.","Confirm the provider is mounted before the consumer — check for conditional/suspense boundaries that delay the provider."],"exampleFix":"// before\nfunction MyLink() {\n  const router = useIonRouter();\n  return <button onClick={() => router.push('/x')}>Go</button>;\n}\n// <App> renders <MyLink /> outside <IonReactRouter>\n\n// after\n<IonReactRouter>\n  <IonRouterOutlet>\n    <Route path=\"/\" component={MyLink} />\n  </IonRouterOutlet>\n</IonReactRouter>","handlingStrategy":"validation","validationCode":"// Ensure the consumer is inside <IonReactRouter> before calling push\nimport { IonRouterContext } from '@ionic/react';\nimport { useContext } from 'react';\nconst ctx = useContext(IonRouterContext);\n// The default context's push throws; detect a missing provider by checking routeInfo\nif (ctx.routeInfo === undefined) {\n  throw new Error('useIonRouter() must be used inside <IonReactRouter>.');\n}\nctx.push('/path');","typeGuard":"function hasIonicRouter(ctx: IonRouterContextState): boolean {\n  return ctx.routeInfo !== undefined;\n}","tryCatchPattern":null,"preventionTips":["Always render components using useIonRouter() inside <IonReactRouter>.","In tests, wrap the component under test with the router provider and a route.","Keep routing-aware components within the router's outlet subtree."],"tags":["react","router","context","provider"],"backgroundTag":null,"analyzedSha":"625f9c38ad8c5db8a6c12df5c1622a36da90f9e3","analyzedAt":"2026-08-12T16:00:25.413Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}