Skip to main content

Using Immer

As you know, when working with immutable objects you often get to what’s called a “spread hell” situations. If you prefer working with immutable objects in an mutable fashion, you can use immer with Akita.

The only thing you need to do is pass the produce function from immer to your store:

todos.store.ts
import { produce } from 'immer';

export interface TodosState extends EntityState<Todo> {
ui: {
filter: VISIBILITY_FILTER
};
}

const initialState = {
ui: { filter: VISIBILITY_FILTER.SHOW_ALL }
};

@StoreConfig({ name: 'todos', producerFn: produce })
export class TodosStore extends EntityStore<TodosState> {
constructor() {
super(initialState);
}
}

Now when you use the store's update function, you'll get the draft version, which you can mutate:

todos.service.ts
export class TodosService {

constructor(private todosStore: TodosStore) { }

updateFilter(filter: VISIBILITY_FILTER) {
this.todosStore.update(state => {
state.ui.filter = filter;
})
}

complete({ id, completed }: Todo) {
this.todosStore.update(id, entity => {
entity.completed = completed;
});
}
}
danger

When you choose to work with immer, you can't return a new value from the callback function:

todosStore.update(id, entity => entity.completed = completed);

This will cause immer to throw. Here's a live example you can play with.