Skip to main content

Immer

Quick start

// API
produce(baseState, recipe: (draftState) => void): nextState
import { produce } from 'immer';

const nextState = produce(baseState, draft = > {
// Update draft here, no need return
draft[1].done = true
draft.push({title: "Tweet about it"})
});

How it works

Step-by-step
  1. Clone a draft object from base state
  2. Update draft (not affect base)
  3. Update state with draft

Immer works

Why using it?

Avoid spead operation hell ...

const handleUpdate = () => {
setSomethingState(prev => ({
...prev,
stateInside: {
...prev.stateInside,
newUpdate
}
}));
}

Using

React.useState

const addTodo = (newTodo) => {
setState(prev => [...prev, newTodo])
}
const updateTodoStatus = (todoId) => {
setState(prev => prev.map(i => {
if (i.id === todoId) {
return { ...i, status: !i.status };
}
return i;
}))
}
const increaseUserVisit = (userId) => {
setState(prev => ({
[userId]: {
...prev[userId],
visitCount: prev[userId] + 1
}
}));
}

Redux - Reducer

const byId = (state, action) => {
switch (action.type) {
case RECEIVE_PRODUCTS:
return {
...state,
...action.products.reduce((obj, product) => {
obj[product.id] = product
return obj
}, {})
}
default:
return state
}
}

References