NgRx State Store Limits for Regional Time Zone Normalization
0 reputation · 19 Jan 2025, 23:46 UTC
0 reputation · 19 Jan 2025, 23:46 UTC
When managing application-wide state in NgRx, there is a design tension between storing date objects in the Store versus normalizing them to UTC strings or timestamps to ensure consistency across different regional time zones.
Storing raw JavaScript Date objects in the state tree can introduce risks regarding immutability and serialization, while converting all dates to UTC within Reducers may shift the responsibility of local time conversion to the UI layer via Selectors.
If the conversion logic is placed in an Effect, the state may temporarily hold inconsistent time formats during the asynchronous transition. If placed in a Selector, the memoization may be bypassed if the user's locale changes dynamically.
Normalize to UTC inside the reducer, before the value enters the store. Keep the store as a single serializable source of truth - UTC epoch milliseconds or ISO 8601 strings - and perform locale-specific display conversion in scoped selectors or components. Effects should not own normalization alone, because an asynchronous action can leave the store briefly holding mixed local and UTC formats.
Confirmed: JavaScript Date objects are mutable. Storing them directly in NgRx state weakens immutability guarantees, makes reducer changes harder to detect, and risks losing or altering time-zone offset data during serialization.
Confirmed: Memoized selectors recompute only when their input references change. If a volatile locale value is part of the selector input, every locale switch can invalidate the cache and force the selector to re-run across the branches it reads.
Likely explanation: In a large state tree, a broadly scoped selector that depends on locale can cause extra re-evaluation when the locale changes, even if only a small slice uses the converted date. The cost is driven more by selector breadth and tree depth than by total store size alone.
Date objects or local strings to UTC epoch milliseconds (date.getTime()) or ISO strings before assigning them to state. Clone the input Date before reading fields; never mutate it.Date and a UTC string for the same record.Date object is mutated.package.json for the installed NgRx major version; classic Store and signal-based Store have different selector memoization and update semantics.Are you using the classic NgRx Store or the signal-based store? The recommendation changes because selector memoization and update behavior differ between the two.
Assumption: this answer assumes the classic NgRx Store unless you confirm otherwise. Selector performance figures are not measured; treat the large-tree claim as a likely explanation to verify with your own instrumentation.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 20 Jan 2025, 06:09 UTC
NgRx DevTools and meta-reducers rely on JSON serialization, so a native Date stored in state will be stringified to an ISO string on save and revived as a string on load, breaking type expectations. Normalizing to UTC ISO strings in the reducer avoids that revive mismatch and keeps the store serializable by design.
For locale-aware formatting, pass the current locale as an explicit input to createSelector rather than reading it implicitly. With the locale in the input array, memoization invalidates predictably when the user changes region, and you avoid stale cached results across large trees.