react reducers_react菜鸟教程

react reducers_react菜鸟教程Reducer是处理状态的另一种方式

什么是 reducer 函数? 为什么要用 reducer?

  • Reducer 是处理状态的另一种方式。通俗来讲,就是可以让你的复杂组件更加干净,代码更加优雅
  • 当你的组件里有好多个状态更新逻辑,并且有些是有一定关联性的,写多个useState会看起来很杂乱,为解决这个问题,我们可以将多个状态更新逻辑整合到一个外部函数,这个函数就是reducer
  • 整合业务逻辑

使用 reducer 整合状态逻辑

举个栗子:

react reducers_react菜鸟教程
从上图我们可以看到,目前这个组件有三个处理逻辑,我们写了三个处理函数,这个组件的每个事件处理程序都通过 setTasks 来更新状态。随着这个组件的不断迭代,其状态逻辑也会越来越多。现在看起来没有什么毛病,但是真实业务场景里,需求往往会更加复杂,我们可以使用下面的方式来让业务逻辑更加清晰明了:

将状态逻辑移到组件之外 reducer 函数中
  • 将设置状态的逻辑 修改 成 dispatch 的一个 action;
  • 编写 一个 reducer 函数;
  • 在你的组件中 使用 reducer

react reducers_react菜鸟教程

看了上面我画的图,是不是感觉reducer很简单哇~ 在真实项目中,我们通常会使用 switch 语句来编写reducer,就像下图

react reducers_react菜鸟教程

既然我们会写了,那该怎么使用呢?
react reducers_react菜鸟教程

代码

tasksReducer.js

export default function tasksReducer(tasks, action) {
  switch (action.type) {
    case 'added': {
      return [
        ...tasks,
        {
          id: action.id,
          text: action.text,
          done: false,
        },
      ];
    }
    case 'changed': {
      return tasks.map((t) => {
        if (t.id === action.task.id) {
          return action.task;
        } else {
          return t;
        }
      });
    }
    case 'deleted': {
      return tasks.filter((t) => t.id !== action.id);
    }
    default: {
      throw Error('未知 action:' + action.type);
    }
  }
}

App.js

import { useReducer } from 'react';
import AddTask from './AddTask.js';
import TaskList from './TaskList.js';
import tasksReducer from './tasksReducer.js';

export default function TaskApp() {
  const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);

  function handleAddTask(text) {
    dispatch({
      type: 'added',
      id: nextId++,
      text: text,
    });
  }

  function handleChangeTask(task) {
    dispatch({
      type: 'changed',
      task: task,
    });
  }

  function handleDeleteTask(taskId) {
    dispatch({
      type: 'deleted',
      id: taskId,
    });
  }

  return (
    <>
      <h1>我今天要做什么呢?</h1>
      <AddTask onAddTask={handleAddTask} />
      <TaskList
        tasks={tasks}
        onChangeTask={handleChangeTask}
        onDeleteTask={handleDeleteTask}
      />
    </>
  );
}

let nextId = 3;
const initialTasks = [
  {id: 0, text: '吃饭', done: true},
  {id: 1, text: '睡觉', done: false},
  {id: 2, text: '打豆豆', done: false},
];

对比 useState 和 useReducer

react reducers_react菜鸟教程

我们观察上图,不难发现:

  • 参数:useReducer 和 useState 很相似,都有初始状态,useReducer 钩子接受 2 个参数: reducer 函数,初始的 state
  • 返回值:useReducer 会返回一个有状态的值和一个设置该状态的函数(在上面案例中就是 dispatch 函数)
  • 代码体积: 多事件相似方式修改 state 时,useReducer 可减少代码量
  • 可读性: 状态更新逻辑简单我们就可以用useState ,逻辑复杂,useReducer 可以将状态更新逻辑与事件处理程序分离
  • 可调试性: useState 出现问题不太好调试,而使用 useReducer 时, 可以在 reducer 函数打印日志

如何编写一个优雅的 reducer

  • reducers 必须纯粹。 即当输入相同时,输出也是相同的。它们不应该包含异步请求、定时器或者任何副作用(对组件外部有影响的操作)。
  • 每个 action 都描述了一个单一的用户交互,即使它会引发数据的多个变化。 举个例子,如果用户在一个由 reducer 管理的表单(包含五个表单项)中点击了 重置按钮,那么 dispatch 一个 reset_form 的 action 比 dispatch 五个单独的 set_field 的 action 更加合理。
还可以使用 Immer 简化 reducers

useImmerReducer 让你可以通过 push 或 arr[i] = 来修改 state。下图描述了,优化前后,代码确实有所减少哦~~
react reducers_react菜鸟教程
Reducers 应该是纯净的,而 Immer 提供了一种特殊的 draft 对象,可以通过它安全修改 state。Immer 在底层基于当前 state 创建一个副本。

今天就写到这里啦~
  • 小伙伴们,( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝ我们明天再见啦~~
  • 大家要天天开心哦

欢迎大家指出文章需要改正之处~
学无止境,合作共赢

在这里插入图片描述

欢迎路过的小哥哥小姐姐们提出更好的意见哇~~

今天的文章react reducers_react菜鸟教程分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/85221.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注