npm install immer use-immer
1️⃣ 概念
useImmer
- 来自 Immer 库。
- 作用:让你在 React state 中可以 直接“修改(
操作)”对象或数组,而不需要手动写展开运算符(...)。 - 内部原理:
Immer 会帮你在后台生成一个新的 immutable state,所以你看起来像是直接修改,但其实是不可变更新。
本质:简化复杂 state 的更新,尤其是嵌套对象/数组。
useImmerReducer
- 和 React 原生的
useReducer类似,但使用 Immer,让 reducer 内可以直接修改 state。 - 传统
useReducer要返回一个新对象:
return {...state, nested: {...state.nested, value: newValue}}
- 使用
useImmerReducer可以直接写:
state.nested.value = newValue
Immer 会帮你生成新的 state。
本质:把 reducer 的不可变更新变成“可变写法”,减少样板代码。
2️⃣ 基本用法
(1)useImmer
import { useImmer } from "use-immer";
function Counter() {
// state 是一个对象
const [state, updateState] = useImmer({ count: 0, nested: { value: 10 } });
const increment = () => {
updateState(draft => {
draft.count += 1; // 直接修改
draft.nested.value += 5; // 嵌套对象也可以直接修改
});
};
return (
<div>
<p>Count: {state.count}</p>
<p>Nested Value: {state.nested.value}</p>
<button onClick={increment}>Increment</button>
</div>
);
}
✅ 优点:
- 可以直接写
draft.count += 1,不需要写...state。 - 嵌套对象/数组修改也很简洁。
(2)useImmerReducer
import { useImmerReducer } from "use-immer";
const initialState = {
count: 0,
todos: []
};
function reducer(state, action) {
switch (action.type) {
case "increment":
state.count += 1; // 直接修改
break;
case "addTodo":
state.todos.push(action.payload); // 直接 push
break;
default:
break;
}
}
function App() {
const [state, dispatch] = useImmerReducer(reducer, initialState);
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "increment" })}>Increment</button>
<button onClick={() => dispatch({ type: "addTodo", payload: "Learn Immer" })}>
Add Todo
</button>
<ul>
{state.todos.map((todo, i) => (
<li key={i}>{todo}</li>
))}
</ul>
</div>
);
}
✅ 优点:
- reducer 写法和普通可变 JS 一样。
- 嵌套更新也非常简单,无需深拷贝。
3️⃣ 总结对比
| Feature | 原生 useState / useReducer | useImmer / useImmerReducer |
|---|---|---|
| 更新对象/数组 | 需要深拷贝或展开运算符 ... | 可以直接修改 draft |
| 嵌套 state 更新 | 很麻烦,需要手动拷贝每一层 | 自动生成新 state,直接修改即可 |
| API | [state, setState] / [state, dispatch] | [state, updateState] / [state, dispatch] |
| 使用场景 | 简单 state 更新 | 嵌套对象/数组,复杂 state 更新 |
💡 小技巧:
- 如果 state 很简单,
useState更轻量。 - 如果 state 很复杂,尤其是嵌套对象、数组频繁修改,
useImmer能极大减少代码量和 bug。