-
Notifications
You must be signed in to change notification settings - Fork 41
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 withpatchState
for 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()
towithReset
inlibs/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
setResetState
in 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.md
with 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
setResetState
to avoid two overlapping reset concepts and steer users topatchState(reset(...))
? - We currently use pseudo-internal members like
_resetState
and__setResetState__
. Should we replace them with unique Symbols to hide internals from users?