spree/spree · error · Error

useStore must be used within a StoreProvider

Error message

useStore must be used within a StoreProvider

What it means

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.

Source

Thrown at packages/dashboard-core/src/providers/store-provider.tsx:108

        isLoading: query.isLoading,
        currencies,
        locales,
        availableLocales,
        defaultCurrency,
        defaultLocale,
        timezone,
        refetch: query.refetch,
      }}
    >
      {children}
    </StoreContext.Provider>
  )
}

export function useStore(): StoreContextValue {
  const context = useContext(StoreContext)
  if (!context) {
    throw new Error('useStore must be used within a StoreProvider')
  }
  return context
}

View on GitHub (pinned to 06bf66a868)

Solutions

  1. Render the component inside <StoreProvider storeId={storeId}> — in the SPA this is the authenticated $storeId route layout
  2. Ensure storeId is available (route params) before rendering consumers; gate on the param existing
  3. In tests, wrap with a provider stack that includes StoreProvider with a test storeId
  4. For components usable outside a store context (account-level pages), take currency/locale/timezone via props instead of useStore()

Example fix

// before
const { store, timezone } = useStore() // throws: no StoreProvider above

// after — inside the store route, where the id is known
<Route path="/stores/$storeId">
  {({ params }) => (
    <StoreProvider storeId={params.storeId}>
      <StorePages />
    </StoreProvider>
  )}
</Route>
Defensive patterns

Strategy: validation

Validate before calling

// Ensure a storeId exists before rendering anything that (transitively) calls useStore()
function StoreRoute({ storeId }: { storeId?: string }) {
  if (!storeId) return <StoreLoading /> // never render consumers without the id
  return (
    <StoreProvider storeId={storeId}>
      <StorePages />
    </StoreProvider>
  )
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of spree/spree@06bf66a868 (2026-08-21). Data as JSON: /api/errors/47ba9ec3e17271eb. Report an issue: GitHub.