Skip to content

Commit

Permalink
fix(signals): Remove the protection for state mutation in dev mode
Browse files Browse the repository at this point in the history
Applying `Object.freeze` on the state caused too many issues
with edge cases, where mutable changes are necessary.

Therefore, this feature is removed.
  • Loading branch information
rainerhahnekamp committed Jan 26, 2025
1 parent 02320b3 commit 26bb6f3
Show file tree
Hide file tree
Showing 6 changed files with 9 additions and 214 deletions.
150 changes: 0 additions & 150 deletions modules/signals/spec/deep-freeze.spec.ts

This file was deleted.

48 changes: 0 additions & 48 deletions modules/signals/src/deep-freeze.ts

This file was deleted.

3 changes: 1 addition & 2 deletions modules/signals/src/signal-state.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { signal } from '@angular/core';
import { STATE_SOURCE, WritableStateSource } from './state-source';
import { DeepSignal, toDeepSignal } from './deep-signal';
import { freezeInDevMode } from './deep-freeze';

export type SignalState<State extends object> = DeepSignal<State> &
WritableStateSource<State>;

export function signalState<State extends object>(
initialState: State
): SignalState<State> {
const stateSource = signal(freezeInDevMode(initialState as State));
const stateSource = signal(initialState as State);
const signalState = toDeepSignal(stateSource.asReadonly());
Object.defineProperty(signalState, STATE_SOURCE, {
value: stateSource,
Expand Down
10 changes: 4 additions & 6 deletions modules/signals/src/state-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
WritableSignal,
} from '@angular/core';
import { Prettify } from './ts-helpers';
import { freezeInDevMode } from './deep-freeze';

const STATE_WATCHERS = new WeakMap<Signal<object>, Array<StateWatcher<any>>>();

Expand Down Expand Up @@ -38,11 +37,10 @@ export function patchState<State extends object>(
): void {
stateSource[STATE_SOURCE].update((currentState) =>
updaters.reduce(
(nextState: State, updater) =>
freezeInDevMode({
...nextState,
...(typeof updater === 'function' ? updater(nextState) : updater),
}),
(nextState: State, updater) => ({
...nextState,
...(typeof updater === 'function' ? updater(nextState) : updater),
}),
currentState
)
);
Expand Down
11 changes: 4 additions & 7 deletions modules/signals/src/with-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
SignalStoreFeature,
SignalStoreFeatureResult,
} from './signal-store-models';
import { freezeInDevMode } from './deep-freeze';

export function withState<State extends object>(
stateFactory: () => State
Expand All @@ -36,12 +35,10 @@ export function withState<State extends object>(

assertUniqueStoreMembers(store, stateKeys);

store[STATE_SOURCE].update((currentState) =>
freezeInDevMode({
...currentState,
...state,
})
);
store[STATE_SOURCE].update((currentState) => ({
...currentState,
...state,
}));

const stateSignals = stateKeys.reduce((acc, key) => {
const sliceSignal = computed(
Expand Down
1 change: 0 additions & 1 deletion projects/ngrx.io/content/guide/signals/signal-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ patchState(
<div class="alert is-critical">

Updaters passed to the `patchState` function must perform state updates in an immutable manner.
If a mutable change occurs to the state object, an error will be thrown in development mode.

</div>

Expand Down

0 comments on commit 26bb6f3

Please sign in to comment.