{"record":{"id":"47ba9ec3e17271eb","repo":"spree/spree","slug":"usestore-must-be-used-within-a-storeprovider","errorCode":null,"errorMessage":"useStore must be used within a StoreProvider","messagePattern":"useStore must be used within a StoreProvider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dashboard-core/src/providers/store-provider.tsx","lineNumber":108,"sourceCode":"        isLoading: query.isLoading,\n        currencies,\n        locales,\n        availableLocales,\n        defaultCurrency,\n        defaultLocale,\n        timezone,\n        refetch: query.refetch,\n      }}\n    >\n      {children}\n    </StoreContext.Provider>\n  )\n}\n\nexport function useStore(): StoreContextValue {\n  const context = useContext(StoreContext)\n  if (!context) {\n    throw new Error('useStore must be used within a StoreProvider')\n  }\n  return context\n}\n","sourceCodeStart":90,"sourceCodeEnd":112,"githubUrl":"https://github.com/spree/spree/blob/06bf66a8684b9de03210bbb2ddc8c1f5ba522fa2/packages/dashboard-core/src/providers/store-provider.tsx#L90-L112","documentation":"Hook from @spree/dashboard-core reading StoreContext, created only by <StoreProvider storeId={...}>. The provider TanStack-Query-fetches the store record (keyed ['store', storeId]) and derives currencies, locales, timezone and defaults for the whole SPA. useStore() throws when called outside that provider.","triggerScenarios":"Calling useStore() in a component rendered outside <StoreProvider>: pages or layout chrome mounted before the store route parameter exists (no storeId to pass), components on unauthenticated routes, portal-rendered overlays, or isolated tests without the provider wrapper.","commonSituations":"Custom host apps that skip the store route wrapper; upgrading @spree/dashboard-core where provider composition moved into the $storeId route layout; tests rendering any component that transitively calls useStore (currency formatting, <StoreDatePicker>); forgetting that StoreProvider requires both a storeId prop and an <AuthProvider> ancestor (it calls useAuth).","solutions":["Render the component inside <StoreProvider storeId={storeId}> — in the SPA this is the authenticated $storeId route layout","Ensure storeId is available (route params) before rendering consumers; gate on the param existing","In tests, wrap with a provider stack that includes StoreProvider with a test storeId","For components usable outside a store context (account-level pages), take currency/locale/timezone via props instead of useStore()"],"exampleFix":"// before\nconst { store, timezone } = useStore() // throws: no StoreProvider above\n\n// after — inside the store route, where the id is known\n<Route path=\"/stores/$storeId\">\n  {({ params }) => (\n    <StoreProvider storeId={params.storeId}>\n      <StorePages />\n    </StoreProvider>\n  )}\n</Route>","handlingStrategy":"validation","validationCode":"// Ensure a storeId exists before rendering anything that (transitively) calls useStore()\nfunction StoreRoute({ storeId }: { storeId?: string }) {\n  if (!storeId) return <StoreLoading /> // never render consumers without the id\n  return (\n    <StoreProvider storeId={storeId}>\n      <StorePages />\n    </StoreProvider>\n  )\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Render the whole store workspace under the $storeId route layout so StoreProvider is unconditionally present","Remember StoreProvider needs an AuthProvider ancestor and a storeId prop — check both when wiring custom hosts","In tests, wrap with StoreProvider plus a test storeId; most formatting components depend on its currency/timezone","Components shared across store/account contexts should take currency/locale/timezone via props"],"tags":["react","typescript","react-context","dashboard-core","multi-store","provider"],"backgroundTag":"react-context-provider-missing","analyzedSha":"06bf66a8684b9de03210bbb2ddc8c1f5ba522fa2","analyzedAt":"2026-08-21T14:59:48.125Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}