ngxs-labs / immer-adapter

:hamster: Declarative state mutations
MIT License
46 stars 10 forks source link
adapter immer ngxs stage-3


Declarative state mutations

Build Status NPM License Codacy Badge

📦 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;
    }));
  }
}