NikeStoreProvider
When to use
Section titled “When to use”Any module scoped to a store needing storeInfo, storeConfig, or athletes.
When NOT to use
Section titled “When NOT to use”Stateless public pages without a store context.
Related stores
Section titled “Related stores”useNikeStoreuseStoreInfoStore
Common pitfalls
Section titled “Common pitfalls”storeIdmust be a valid UUID.storeConfigandathletesrequireloggedIn={true}andaccessToken.- Provider does not relay host auth — pass tokens to child components that need them.
Data sources
Section titled “Data sources”| 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.
Appended/elevated fields on info
Section titled “Appended/elevated fields on info”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. |
Athlete shape
Section titled “Athlete shape”| Property | Type | Description |
|---|---|---|
operatorId |
string |
Employee number — useful for incident “Requested For” lookups. |
givenName |
string |
First name |
familyName |
string |
Last name |
Error handling
Section titled “Error handling”Every fetch failure is captured in two ways:
- 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. - The provider routes the same error through the analytics service under
moduleName: 'whisker-component-library',feature: 'NikeStoreProvider', with anoperationattribute (fetchStoreInfo/fetchStoreConfig/fetchAthletes). Hosts that mount aPlatformAnalyticsProviderwill see those errors in New Relic out-of-the-box.
Caching
Section titled “Caching”infoandathletespersist tolocalStorageunder the keynike-store-infowith a 24-hour TTL. Stale entries are cleared on read.configis never persisted — it’s fetched fresh on every login and cleared on logout.- Switching
storeIdwipes the cache for the previous store and triggers a fresh fetch for the new one.
Best practices
Section titled “Best practices”- 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
accessTokenfrom a stale snapshot — read it from your auth store every render so the prop tracks token rotation. - Don’t nest multiple
NikeStoreProviders for the samestoreIdin one tree — the inner one shadows the outer.
Auto-generated from
src/types/storeInfo.types.ts. Do not edit by hand. Runpnpm docs:propsafter changing source JSDoc.
NikeStoreProviderProps
Section titled “NikeStoreProviderProps”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) |
NikeStoreContextValue
Section titled “NikeStoreContextValue”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). |
Examples
Section titled “Examples”Standard store context
Section titled “Standard store context”import { NikeStoreProvider } from '@nike/whisker-component-library';
<NikeStoreProvider storeId={storeId} loggedIn={isLoggedIn} accessToken={token} isProd={isProd} bffUrl={bffUrl}> <StoreDashboard /></NikeStoreProvider>;Public store info only (no auth)
Section titled “Public store info only (no auth)”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> );}Cross-module sharing
Section titled “Cross-module sharing”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 / ModuleBconst store = useNikeStore();const operators = store?.athletes ?? [];