-
Notifications
You must be signed in to change notification settings - Fork 44
Description
Many apps need to re-initialize only parts of a store (e.g., clear a callState or selected slices) rather than resetting everything. Since state changes are mutations, they should be expressed as updater functions passed to patchState so multiple updates can run atomically and the Signal Store remains the only state mutation point.
Today, resetState is an instance method that can be called anywhere and may collide with other feature methods; it also doesn’t support partial resets.
This proposal introduces a type-safe reset() function - usable only inside patchState - for full and partial resets, as discussed here: PR #160 review comment.
Problem
withReset()currently resets the entire store; projects often need to reset only selected slices.- Mutations should be modeled as updater functions passed to
patchState resetState(instance method) can collide with other features
Proposal
Introduce a reset() function that returns an updater function for patchState and allows full and partial resets with strong typing (no string paths). Deprecate resetState.
// Full reset
function reset<TState>(): (state: TState) => TState;
// Partial reset (selected top-level slices)
function reset<TState, K extends keyof TState>(
pick: (initial: TState) => Pick<TState, K>
): (state: TState) => TState;Example
// Full reset
patchState(store, reset());
// Partial reset of top-level slices
patchState(store, reset(initial => ({ address: initial.address, user: initial.user })));- Partial resets copy selected slices from the stored initial snapshot.
- Deep string paths like
'address.city'are intentionally not supported to keep the API simple and type-safe. Compose updates or add targeted helpers for nested cases.
Acceptance Criteria
reset()works withpatchStatefor full and partial resets.- Type-safe selection of slices (no string keys/paths).
- Backward compatibility: existing code continues to work.
- Tests cover:
- Full reset
- Partial reset for one and multiple keys
- Nested objects where only selected top-level keys are reset
- Immutability preserved and atomicity via
patchState
- Documentation clearly explains the new API, usage, and deprecations.
Implementation Details
- Add
reset()towithResetinlibs/ngrx-toolkit/src/lib/with-reset.ts.- Use the stored initial/reset snapshot (e.g.,
store._resetState) to compute next state. - Provide overloads for full and partial reset as above.
- Use the stored initial/reset snapshot (e.g.,
- Update docs in
docs/docs/with-reset.md. - Add tests in
libs/ngrx-toolkit/src/lib/with-reset.spec.ts.
Deprecation Plan
- Deprecate
resetState(instance method) in types and docs; keep runtime behavior for now. - Consider also deprecating
setResetStatein favor of a singlereset()flow (see questions).
Tasks
- Implement
reset()(full + partial) inlibs/ngrx-toolkit/src/lib/with-reset.ts - Add unit tests in
libs/ngrx-toolkit/src/lib/with-reset.spec.ts - Update docs:
docs/docs/with-reset.mdwith API and examples - Update demo(s) to showcase
reset()viapatchState - Deprecate
resetState
References
- Review proposing
reset()insidepatchState: PR #160 review comment
Further Questions
- Should we also deprecate
setResetStateto avoid two overlapping reset concepts and steer users topatchState(reset(...))? - We currently use pseudo-internal members like
_resetStateand__setResetState__. Should we replace them with unique Symbols to hide internals from users?