useReducer 钩子函数
1、useReducer 钩子函数简要说明
useReducer 钩子函数的作用跟 useState 一样,即对数据进行管理,但是 useReducer 对状态数据的管理是通过配套的 dispatch 方法来管理,这也是和 useState 不同的地方。
2、useReducer 官方例子
const ACTION = {
increment: "increment",
decrement: "decrement",
};
const UseReducerDemo1: React.FC = () => {
const initialState = { count: 0 };
const [state, dispatch] = useReducer(reducer, initialState);
function reducer(state: { count: number }, action: { type: string }) {
switch (action.type) {
case ACTION.increment:
return { count: state.count + 1 };
case ACTION.decrement:
return { count: state.count - 1 };
default:
throw new Error();
}
}
return (
<div>
<button onClick={() => dispatch({ type: ACTION.decrement })}>-</button>
<p>{state.count}</p>
<button onClick={() => dispatch({ type: ACTION.increment })}>+</button>
</div>
);
};
3、useReducer TODO 例子
const ACTIONS = {
ADD_TODO: "add_todo",
SWITCH_TODO: "switch_todo",
DELETE_TODO: "delete_todo",
};
type todoItem = { id: number; name: string; isFinish: boolean };
const UseReducerDemo2: React.FC = () => {
const [todoName, setTodoName] = useState<string>("");
const [todos, dispatch] = useReducer(reducer, []);
function reducer(todos: any[], action: any) {
switch (action.type) {
case ACTIONS.ADD_TODO:
return [...todos, newTodo(todoName)];
case ACTIONS.SWITCH_TODO:
return todos.map((item: todoItem) => {
if (action.item.id === item.id) {
return { ...item, isFinish: !item.isFinish };
}
return item;
});
case ACTIONS.DELETE_TODO:
return todos.filter((item: todoItem) => item.id !== action.item.id);
default:
return todos;
}
}
function newTodo(name: string) {
const _name = name;
setTodoName("");
return { id: new Date().getTime(), name: _name, isFinish: false };
}
function handleSumit(e: FormEvent) {
e.preventDefault();
dispatch({ type: ACTIONS.ADD_TODO });
}
return (
<>
<form onSubmit={handleSumit}>
<input
type="text"
value={todoName}
onChange={(e) => setTodoName(e.target.value)}
/>
<button type="submit">提交</button>
</form>
<div>
{todos.map((item: todoItem) => (
<div key={item.id}>
<span style={{ color: item.isFinish ? "#aaa" : "#333" }}>
{item.name} - {item.isFinish ? "1" : "2"}
</span>
<button
onClick={() => dispatch({ type: ACTIONS.SWITCH_TODO, item })}
>
切换
</button>
<button
onClick={() => dispatch({ type: ACTIONS.DELETE_TODO, item })}
>
删除
</button>
</div>
))}
</div>
</>
);
};