Declarative state mutations
📦 Install
To install @ngxs-labs/immer-adapter
and immer
that is a peer-dependency run the following command:
npm install @ngxs-labs/immer-adapter immer
# or if you use yarn
yarn add @ngxs-labs/immer-adapter immer
Before
When your state is growing - it becomes harder to manage such mutations:
import { State, Action, StateContext } from '@ngxs/store';
export class FeedZebra {
public static readonly type = '[Animals] Feed zebra';
constructor(public payload: string) {}
}
@State<AnimalsStateModel>({
name: 'animals',
defaults: {
zebra: {
food: ['leaves', 'bark'],
name: 'zebra'
},
panda: {
food: [],
name: 'panda'
}
}
})
export class AnimalState {
@Selector()
public static zebraFood(state: AnimalsStateModel): string[] {
const zebraFood = [...state.zebra.food];
zebraFood.reverse();
}
@Action(Add)
public add({ getState, setState }: StateContext<AnimalsStateModel>, { payload }: Add): void {
setState((state: AnimalsStateModel) => ({
...state,
zebra: {
...state.zebra,
food: [ ...state.zebra.food, payload ]
}
}));
}
}
After
immer-adapter
gives you the opportunity to manage mutations in a more declarative way:
import { ImmutableContext, ImmutableSelector } from '@ngxs-labs/immer-adapter';
@State<AnimalsStateModel>({
name: 'animals',
defaults: {
zebra: {
food: [],
name: 'zebra'
},
panda: {
food: [],
name: 'panda'
}
}
})
export class AnimalState {
@Selector()
@ImmutableSelector()
public static zebraFood(state: AnimalsStateModel): string[] {
return state.zebra.food.reverse();
}
@Action(Add)
@ImmutableContext()
public add({ setState }: StateContext<AnimalsStateModel>, { payload }: Add): void {
setState((state: AnimalsStateModel) => ({
state.zebra.food.push(payload);
return state;
}));
}
}