Skip to content

Commit ae7922e

Browse files
fix(signals): revert the protection for state mutation in dev mode (#4686)
Closes #4683
1 parent 44cb328 commit ae7922e

File tree

7 files changed

+9
-257
lines changed

7 files changed

+9
-257
lines changed

modules/signals/spec/deep-freeze.spec.ts

-150
This file was deleted.

modules/signals/src/deep-freeze.ts

-48
This file was deleted.

modules/signals/src/signal-state.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { signal } from '@angular/core';
22
import { STATE_SOURCE, WritableStateSource } from './state-source';
33
import { DeepSignal, toDeepSignal } from './deep-signal';
4-
import { freezeInDevMode } from './deep-freeze';
54

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

98
export function signalState<State extends object>(
109
initialState: State
1110
): SignalState<State> {
12-
const stateSource = signal(freezeInDevMode(initialState as State));
11+
const stateSource = signal(initialState as State);
1312
const signalState = toDeepSignal(stateSource.asReadonly());
1413
Object.defineProperty(signalState, STATE_SOURCE, {
1514
value: stateSource,

modules/signals/src/state-source.ts

+4-6
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
WritableSignal,
99
} from '@angular/core';
1010
import { Prettify } from './ts-helpers';
11-
import { freezeInDevMode } from './deep-freeze';
1211

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

@@ -38,11 +37,10 @@ export function patchState<State extends object>(
3837
): void {
3938
stateSource[STATE_SOURCE].update((currentState) =>
4039
updaters.reduce(
41-
(nextState: State, updater) =>
42-
freezeInDevMode({
43-
...nextState,
44-
...(typeof updater === 'function' ? updater(nextState) : updater),
45-
}),
40+
(nextState: State, updater) => ({
41+
...nextState,
42+
...(typeof updater === 'function' ? updater(nextState) : updater),
43+
}),
4644
currentState
4745
)
4846
);

modules/signals/src/with-state.ts

+4-7
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
SignalStoreFeature,
1010
SignalStoreFeatureResult,
1111
} from './signal-store-models';
12-
import { freezeInDevMode } from './deep-freeze';
1312

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

3736
assertUniqueStoreMembers(store, stateKeys);
3837

39-
store[STATE_SOURCE].update((currentState) =>
40-
freezeInDevMode({
41-
...currentState,
42-
...state,
43-
})
44-
);
38+
store[STATE_SOURCE].update((currentState) => ({
39+
...currentState,
40+
...state,
41+
}));
4542

4643
const stateSignals = stateKeys.reduce((acc, key) => {
4744
const sliceSignal = computed(

projects/ngrx.io/content/guide/migration/v19.md

-43
Original file line numberDiff line numberDiff line change
@@ -23,49 +23,6 @@ Version 19 has the minimum version requirements:
2323

2424
### Signals
2525

26-
#### Throw error in dev mode on state mutation
27-
28-
The `patchState` method applies a deep freeze on the state in dev mode.
29-
If you try to update the state directly, it will throw an error in dev mode.
30-
31-
BEFORE:
32-
33-
```ts
34-
const userState = signalState(initialState);
35-
patchState(userState, (state) => {
36-
// mutable change which went through
37-
state.user.firstName = 'mutable change';
38-
return state;
39-
});
40-
```
41-
42-
AFTER:
43-
44-
```ts
45-
const userState = signalState(initialState);
46-
patchState(userState, (state) => {
47-
// mutable change throws in dev mode
48-
state.user.firstName = 'mutable change';
49-
return state;
50-
});
51-
```
52-
53-
To fix the error, update the state in an immutable way.
54-
55-
```ts
56-
const userState = signalState(initialState);
57-
patchState(userState, (state) => {
58-
return {
59-
...state,
60-
user: {
61-
...state.user,
62-
// immutable change which went through
63-
firstName: 'immutable change',
64-
},
65-
};
66-
});
67-
```
68-
6926
#### `computed` is replaced with `props`
7027

7128
To support more cases, the `props` property is added to `signalStoreFeature`, which replaces the existing `computed` property.

projects/ngrx.io/content/guide/signals/signal-state.md

-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ patchState(
8787
<div class="alert is-critical">
8888

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

9291
</div>
9392

0 commit comments

Comments
 (0)