Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: add breaking changes to v19 migration #4620

Merged
merged 2 commits into from
Dec 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 143 additions & 1 deletion projects/ngrx.io/content/guide/migration/v19.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,146 @@ Version 19 has the minimum version requirements:

## Breaking changes

TODO
### Signals

#### Throw error in dev mode on state mutation

The `patchState` method applies a deep freeze on the state in dev mode.
If you try to update the state directly, it will throw an error in dev mode.

BEFORE:

```ts
const userState = signalState(initialState);
patchState(userState, (state) => {
// mutable change which went through
state.user.firstName = 'mutable change';
return state;
});
```

AFTER:

```ts
const userState = signalState(initialState);
patchState(userState, (state) => {
// mutable change throws in dev mode
state.user.firstName = 'mutable change';
return state;
});
```

To fix the error, update the state in an immutable way.

```ts
const userState = signalState(initialState);
patchState(userState, (state) => {
return {
...state,
user: {
...state.user,
// immutable change which went through
firstName: 'immutable change',
},
};
});
```

#### `computed` is replaced with `props`

To support more cases, the `props` property is added to `signalStoreFeature`, which replaces the existing `computed` property.
This change has an ng-update schematic that automatically updates your code.

- The `computed` property in the `SignalStoreFeature` type is renamed to `props`.
- The `computed` property in the `signalStoreFeature` method is renamed to `props`.
- The `EntityComputed` and `NamedEntityComputed` types in the `entities` plugin are renamed to `EntityProps` and `NamedEntityProps`.

BEFORE:

```ts
import { computed, Signal } from '@angular/core';
import {
signalStoreFeature,
SignalStoreFeature,
type,
withComputed,
} from '@ngrx/signals';
import { EntityComputed } from '@ngrx/signals/entities';

export function withTotalEntities<Entity>(): SignalStoreFeature<
{ state: {}, computed: EntityComputed<Entity>, methods: {} },
{ state: {}, computed: { total: Signal<number> }, methods: {} },
> {
return signalStoreFeature(
{ computed: type<EntityComputed<Entity>>() },
withComputed(({ entities }) => ({
total: computed(() => entities().length),
})),
);
}
```

AFTER:

```ts
import { computed, Signal } from '@angular/core';
import {
signalStoreFeature,
SignalStoreFeature,
type,
withComputed,
} from '@ngrx/signals';
import { EntityProps } from '@ngrx/signals/entities';

export function withTotalEntities<Entity>(): SignalStoreFeature<
{ state: {}, props: EntityProps<Entity>, methods: {} },
{ state: {}, props: { total: Signal<number> }, methods: {} },
> {
return signalStoreFeature(
{ props: type<EntityProps<Entity>>() },
withComputed(({ entities }) => ({
total: computed(() => entities().length),
})),
);
}
```

#### Rename `rxMethod.unsubscribe()` to `rxMethod.destroy()`

The `unsubscribe` method from `rxMethod` is renamed to `destroy`.

BEFORE:

```ts
const logNumber = rxMethod<number>(tap(console.log));

const num1Ref = logNumber(interval(1_000));
const num2Ref = logNumber(interval(2_000));

// destroy `num1Ref` after 2 seconds
setTimeout(() => num1Ref.unsubscribe(), 2_000);

// destroy all reactive method refs after 5 seconds
setTimeout(() => logNumber.unsubscribe(), 5_000);
```

AFTER:

```ts
const logNumber = rxMethod<number>(tap(console.log));

const num1Ref = logNumber(interval(1_000));
const num2Ref = logNumber(interval(2_000));

// destroy `num1Ref` after 2 seconds
setTimeout(() => num1Ref.destroy(), 2_000);

// destroy all reactive method refs after 5 seconds
setTimeout(() => logNumber.destroy(), 5_000);
```

### Schematics

#### Standalone is the default

(Container) components created by the Container Schematic are now standalone by default.
Loading