Skip to content

NikeStoreProvider

Any module scoped to a store needing storeInfo, storeConfig, or athletes.

Stateless public pages without a store context.

  • useNikeStore
  • useStoreInfoStore
  • storeId must be a valid UUID.
  • storeConfig and athletes require loggedIn={true} and accessToken.
  • Provider does not relay host auth — pass tokens to child components that need them.
Resource Source Auth? Persisted?
info Nike Store Views v2 No (public) Yes — localStorage 24h
config SIM BFF /config/v1 Yes (Bearer) No — fresh per session
athletes SIM BFF /athletes/v1 Yes (Bearer) Yes — localStorage 24h

When loggedIn flips from true to false the provider auto-clears config and athletes. info is preserved across logout because it’s public data.

The full raw payload from Store Views v2 is preserved on info. On top of that, SIM enriches info with derived fields — most flatten nested values to the root so consumers don’t need to reach into address, currencies, or region for common reads.

Field Source Why we elevate it
country address.country Frequently needed for filtering, formatting, and analytics.
merchGroup address.iso2Country Used for merchandising/catalog scoping. ISO-2 is more stable than the long-form country name.
countryStoreNumber Composed: `${country}-${storeNumber}` Human-readable store identifier (e.g. "USA-128") used in incident references and UI badges.
currencyCode currencies[0] Most stores report a single currency; surfacing the primary one avoids consumers indexing into the array.
currencySymbol Computed via Intl.NumberFormat The contract returns codes only; the locale-aware symbol is derived once so every consumer doesn’t repeat it.
isNorthAmerica / isEMEA / isAPLA / isGreaterChina Derived from region Boolean flags read better than string compares; default to isNorthAmerica = true when region is missing.
serverRegion Looked up by country in region-map.json Maps a store to its closest AWS region for downstream BFF/data routing (defaults to "us-east-1").
id The requested storeId Always re-asserted on the response so consumers can rely on a stable UUID even if upstream omits it.
Property Type Description
operatorId string Employee number — useful for incident “Requested For” lookups.
givenName string First name
familyName string Last name

Every fetch failure is captured in two ways:

  1. The most recent error is exposed via useNikeStore().error — surface it in your UI and let the user retry by reloading or selecting another store.
  2. The provider routes the same error through the analytics service under moduleName: 'whisker-component-library', feature: 'NikeStoreProvider', with an operation attribute (fetchStoreInfo / fetchStoreConfig / fetchAthletes). Hosts that mount a PlatformAnalyticsProvider will see those errors in New Relic out-of-the-box.
  • info and athletes persist to localStorage under the key nike-store-info with a 24-hour TTL. Stale entries are cleared on read.
  • config is never persisted — it’s fetched fresh on every login and cleared on logout.
  • Switching storeId wipes the cache for the previous store and triggers a fresh fetch for the new one.
  • Place the provider at your module root, below your platform-level providers (analytics, theme).
  • Always render loading and error states from isLoading / error.
  • Don’t pass accessToken from a stale snapshot — read it from your auth store every render so the prop tracks token rotation.
  • Don’t nest multiple NikeStoreProviders for the same storeId in one tree — the inner one shadows the outer.

Auto-generated from src/types/storeInfo.types.ts. Do not edit by hand. Run pnpm docs:props after changing source JSDoc.

NikeStoreProvider component props

Prop Type Required Description
accessToken null | string No Current access token string (required for storeConfig) Kept up-to-date reactively by the host’s auth state.
bffUrl string No Explicit BFF base URL (e.g. http://localhost:4000). When provided it overrides prod/test resolution — use this for local dev or custom deploy overrides. Replaces the previous isLocal flag.
children React.ReactNode Yes Children components
isProd boolean No Whether running in production mode (affects API endpoints) Default: false
loggedIn boolean No Whether user is logged in (controls storeConfig fetching) storeInfo is always fetched (public API) storeConfig only fetched when loggedIn=true (requires auth) Default: false
storeId string Yes Store ID to fetch information for (UUID format)

Context value exposed by useNikeStore(). Intentionally narrow — the provider’s job is to surface store data, not to relay host-supplied values like the access token. Components that need the SIM access token should accept it as a prop directly.

Prop Type Required Description
athletes Athlete[] | null Yes Athletes for the store (requires auth, cached 24h).
config null | StoreConfig Yes Store-specific configuration (requires auth; never persisted).
error Error | null Yes Most recent fetch error across info, config, and athletes. Cleared on the next successful fetch of the same resource. null when all resources are healthy.
info null | StoreInfo Yes Store information and metadata.
isLoading boolean Yes True while any of info, config, or athletes is being fetched.
storeId null | string Yes Currently active store ID (matches the most recently committed fetch).
import { NikeStoreProvider } from '@nike/whisker-component-library';
<NikeStoreProvider
storeId={storeId}
loggedIn={isLoggedIn}
accessToken={token}
isProd={isProd}
bffUrl={bffUrl}
>
<StoreDashboard />
</NikeStoreProvider>;
import { NikeStoreProvider, useNikeStore } from '@nike/whisker-component-library';
function App() {
return (
<NikeStoreProvider storeId="ed3d4e6f-4b53-4b81-aae2-c90f0a775532">
<StoreBadge />
</NikeStoreProvider>
);
}
function StoreBadge() {
const store = useNikeStore();
if (store?.isLoading) return <div>Loading…</div>;
if (store?.error) return <div>Error: {store.error.message}</div>;
return (
<span>
Store {store?.info?.storeNumber}{store?.info?.currencySymbol}
</span>
);
}

Multiple modules under the same host can each mount a NikeStoreProvider with the same storeId — they share the underlying Zustand store, so only one fetch happens and all subscribers see the same data.

// host
<PlatformAnalyticsProvider
config={
{
/* ... */
}
}
>
<NikeStoreProvider storeId={storeId} loggedIn accessToken={token}>
<ModuleA />
<ModuleB />
</NikeStoreProvider>
</PlatformAnalyticsProvider>;
// inside ModuleA / ModuleB
const store = useNikeStore();
const operators = store?.athletes ?? [];