Skip to main content

Using Immer

When working with immutable objects, we often get to what’s called a “spread hell” situation. If you prefer working with immutable objects in a mutable fashion, you can use immer with Elf.

Create a mutation function:

store/mutations.ts
import { produce } from 'immer';

export function write<S>(updater: (state: S) => void): (state: S) => S {
return function (state) {
return produce(state, (draft) => {
updater(draft as S);
});
};
}

Now you can use it in the store's update function:

todos.respository.ts
import { withProps, createStore } from '@ngneat/elf';
import { withEntities, selectAllEntities, updateEntities } from '@ngneat/elf-entities';

interface Todo {
id: number;
title: string;
completed: boolean;
}

export interface TodosProps {
filter: 'ALL' | 'ACTIVE' | 'COMPLETED';
}

const store = createStore(
{ name: 'todos' },
withEntities<Todo>(),
withProps<TodosProps>({ filter: 'ALL' })
);

export const todos$ = store.pipe(selectAllEntities());

export function updateFilter(filter: TodosProps['filter']) {
store.update(
write((state) => {
state.filter = filter;
})
);
}

export function updateCompleted(id: Todo['id']) {
store.update(
updateEntities(
id,
write<Todo>((entity) => (entity.completed = !entity.completed))
)
);
}