基本使用

  1. const [state, dispatch] = useReducer(reducer, initialArg, init);

它接收一个形如 (state, action) => newState 的 reducer,和初始的state值
并返回当前的 state 以及与其配套的 dispatch 方法。

  1. 第一个参数 reducer 显然是必须的,它的形式跟 Redux 中的 Reducer 函数完全一致,即 (state, action) => newState。
  2. 第二个参数 initialArg 就是状态的初始值。
  3. 第三个参数 init 是一个可选的用于懒初始化(Lazy Initialization)的函数,这个函数返回初始化后的状态。
  1. import React, { useReducer } from "react";
  2. import "./style.css";
  3. //定义初始state
  4. const initialTodos = [
  5. {
  6. id: "a",
  7. task: "Learn React",
  8. complete: false
  9. },
  10. {
  11. id: "b",
  12. task: "Learn Firebase",
  13. complete: true
  14. }
  15. ];
  16. //定义reducer
  17. const todoReducer = (state, action) => {
  18. switch (action.type) {
  19. case "DO_TODO":
  20. return state.map(todo => {
  21. if (todo.id === action.id) {
  22. return { ...todo, complete: true };
  23. } else {
  24. return todo;
  25. }
  26. });
  27. case "UNDO_TODO":
  28. return state.map(todo => {
  29. if (todo.id === action.id) {
  30. return { ...todo, complete: false };
  31. } else {
  32. return todo;
  33. }
  34. });
  35. default:
  36. return state;
  37. }
  38. };
  39. const App = () => {
  40. //初始的todos是initialTodos
  41. const [todos, dispatch] = React.useReducer(todoReducer, initialTodos);
  42. const handleChange = todo => {
  43. dispatch({ type: todo.complete ? "UNDO_TODO" : "DO_TODO", id: todo.id });
  44. };
  45. return (
  46. <ul>
  47. {todos.map(todo => (
  48. <li key={todo.id}>
  49. <label>
  50. <input
  51. type="checkbox"
  52. checked={todo.complete}
  53. onChange={() => handleChange(todo)}
  54. />
  55. {todo.task}
  56. </label>
  57. </li>
  58. ))}
  59. </ul>
  60. );
  61. };
  62. 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 使用起来较为繁琐,但如果你的状态管理出现了至少一个以下所列举的问题:

  • 需要维护的状态本身比较复杂,多个状态之间相互依赖
  • 修改状态的过程比较复杂

Reference

https://www.robinwieruch.de/react-usereducer-hook