基本使用
const [state, dispatch] = useReducer(reducer, initialArg, init);
它接收一个形如 (state, action) => newState
的 reducer,和初始的state值
并返回当前的 state 以及与其配套的 dispatch
方法。
- 第一个参数 reducer 显然是必须的,它的形式跟 Redux 中的 Reducer 函数完全一致,即 (state, action) => newState。
- 第二个参数 initialArg 就是状态的初始值。
- 第三个参数 init 是一个可选的用于懒初始化(Lazy Initialization)的函数,这个函数返回初始化后的状态。
import React, { useReducer } from "react";
import "./style.css";
//定义初始state
const initialTodos = [
{
id: "a",
task: "Learn React",
complete: false
},
{
id: "b",
task: "Learn Firebase",
complete: true
}
];
//定义reducer
const todoReducer = (state, action) => {
switch (action.type) {
case "DO_TODO":
return state.map(todo => {
if (todo.id === action.id) {
return { ...todo, complete: true };
} else {
return todo;
}
});
case "UNDO_TODO":
return state.map(todo => {
if (todo.id === action.id) {
return { ...todo, complete: false };
} else {
return todo;
}
});
default:
return state;
}
};
const App = () => {
//初始的todos是initialTodos
const [todos, dispatch] = React.useReducer(todoReducer, initialTodos);
const handleChange = todo => {
dispatch({ type: todo.complete ? "UNDO_TODO" : "DO_TODO", id: todo.id });
};
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
<label>
<input
type="checkbox"
checked={todo.complete}
onChange={() => handleChange(todo)}
/>
{todo.task}
</label>
</li>
))}
</ul>
);
};
export default App;
- 定义reducer
- 初始化useReducer
- 根据业务需要 dispatch对应的action,{ type: todo.complete ? “UNDO_TODO” : “DO_TODO”, id: todo.id }就是一个action
通过源码分析,Hooks源码可以看到,useState其实是一种阉割版的useReducer
那么,我们什么时候用state,什么时候用recuder呢?
useReducer 和 useState 的使用目的几乎是一样的:定义状态和修改状态的逻辑。useReducer 使用起来较为繁琐,但如果你的状态管理出现了至少一个以下所列举的问题:
- 需要维护的状态本身比较复杂,多个状态之间相互依赖
- 修改状态的过程比较复杂