自学内容网 自学内容网

React第十五节useReducer使用详解差异

useReducer() 的用法注意事项

1、 概述:

useReducer() 常用于管理复杂的状态更新逻辑,特别是在状态更新依赖于多个条件动作时useReducer 提供了一种更加结构化和可维护的方式来处理状态。可以将更新函数写在组件外面
它与 useState() 相似,useState() 用于处理相对简单的状态更新逻辑

2、什么是useReducer():

它是React 提供的一个 HOOK,用于处理复杂的状态管理,特别是更新逻辑比较复杂,或者有多个状态相互依赖的逻辑业务中;

useReducer(reducer, initialArg, init?) 接收三个参数
第一个参数:reducer 用于更新 state纯函数,function(state, action) {};函数接收两个参数 state、action
其中 state 是只能读取的状态值,不能在纯函数里面进行直接修改
其中 action 是用户进行操作的函数,
第二个参数initialArg:用于初始化 state 的任意值,在没有第三个参数时候,直接取当前值为默认值,
第三个参数:init:为可选参数,用于处理state 的默认值函数

3、基本写法:

const [count, dispatch] = useReducer(reducer, initState, initFunc)

useReducer(): 利用数组解构,得到两个参数,
count:当前state的初始值,
dispatch:用于触发count 更新的分发函数;
通常为一个包含type属性的对象;如

const [count, dispatch] = useReducer(reducer, {count: 1}, initFunc)
function handleDispatch() {
  dispatch({type: 'ADD'})
}

4、 具体使用例子

国庆出游计划 增删改成游玩项目

4.1 、声明reducer逻辑处理函数

注意:跟useState 一样,修改数组、对象时候,需要修改其指针,否则React视为当前值没有发生改变

// taskReducer 文件
export default function taskReducer(tasks, action) {
    switch(action.type) {
        case 'added':{
            return [
                ...tasks,
                {
                    id: action.id,
                    text: action.text,
                    done: false,
                }
            ]
        }
        case 'changed' : {
            return tasks.map(itm => {
                    if (itm.id === action.task.id) {
                        return action.task
                    } else {
                        return itm
                    }
                }
            )
        }
        case 'deleted' : {
            return tasks.filter(itm => itm.id!== action.id)
        }

    }
}


a、在 reducer 函数中 通常我们会使用 switch 进行处理type类型条件,当然了你也可以使用if() {}语句,
btaskReducer 函数中设计了新增、删除、修改三个类型;
c、根据传入的 action 中type类型来处理更新 tasks 的状态;

4.2、在组件中使用 useReducer

声明一个任务组件TaskApp

import { useState, useReducer } from 'react'
import taskReducer from './taskReducer'
  // ...
export default function TaskApp() {
    const [tasks, dispatch] = useReducer(taskReducer, initialTasks)
    //...
}
// 声明初始值
const initialTasks = [
  {id: 0, text: '参观卡夫卡博物馆', done: true},
  {id: 1, text: '看木偶戏', done: false},
  {id: 2, text: '打卡列侬墙', done: false}
];

此时我们得到一个tasks 初始值,以及一个dispatch 分发函数
通过调用 dispatch 来触发 taskReducer 函数中对应条件执行
比如要删除一个旅游项目

// ...
function handleDeleteTask(taskId) {
    dispatch({
        type: 'deleted',  // 直接传入 type类型为 deleted,
        id: taskId,
    })
}
// ...

4.3、完整代码

// TaskApp 组件文件
import { useReducer } from 'react'
// 新增旅游项目组件
import AddTask from './taskAdd'
// 旅游项目列表组件
import TaskList from './taskList'
export default function TaskApp() {
    const [tasks, dispatch] = useReducer(taskReducer, initialTasks)
    // 使用dispatch 触发新增操作
    function handleAddTask(text) {
        console.log('==handleAddTask=', nextId)
        dispatch({
            type:'added',
            id: nextId++,
            text: text,
        })
    }
    function handleChangeTask(task) {
        console.log('=handleChangeTask==', task)
        dispatch({
            type:'changed',
            task: task
        })
    }
    // 删除操作
    function handleDeleteTask(taskId) {
        dispatch({
            type: 'deleted',
            id: taskId,
        })
    }
    return (
        <>
          <h1 style={{color: 'red'}}>国庆旅游计划</h1>
          <AddTask onAddTask={handleAddTask}></AddTask>
          <TaskList 
              tasks={tasks}
              onChangeTask={handleChangeTask}
              onDeleteTask={handleDeleteTask}
          ></TaskList>
        </>
    )
}
let nextId = 3;

AddTask 组件中,新增操时候 重置了input 输入框的值,
同时给父组件传递了onAddTask 函数,触发父组件中的 handleAddTask 函数执行;

// AddTask 文件
import { useState } from 'react'
export default  function AddTask ({onAddTask}) {
    const [text, setText] = useState('')
    console.log('===useState==', useState())
    // 通过useState 的setText 触发视图更新
    function handleChangeText(text) {
        setText(text)
    }

    return (
        <>
            <input type="text" value={text} onChange={e => handleChangeText(e.target.value)} />
            <button onClick={() => {
                setText('')
                onAddTask(text)
            }}>新增</button>
        </>
    )
    
}

TaskList 文件中传入 最新的 tasks 以及修改onChangeTask、删除onDeleteTask 函数

// TaskList 文件
export default function TaskList ({tasks, onChangeTask, onDeleteTask}) {
  return (
    <>
      <ul>
        {
          tasks.map((itm, index) =>{
            return (
              <li key={itm.id}>
                  <span>{index + 1}</span>
                  <input type="text" value={itm.text} onChange={(e) => onChangeTask({...itm, text: e.target.value})}/>
                  <button onClick={() => onDeleteTask(itm.id)}>Delete</button>
              </li>
            )
          })
        }
      </ul>
    </>
  )
}

useReducer 与 useState相比较

异同

1、useReducer 更倾向于处理多逻辑状态,useState 倾向于处理单逻辑状态;
2、useReducer 可以处理 所有 useState 处理的 更新的属性
3、都必须在最组件的最顶层调用不能条件语句或者循环中使用;
4、初始化的时候 都会被调用 两次用于检查代码中的意外不纯粹性;
5、都可以触发视图更新

useReducer 的优缺点

优点:

代码统一组织管理:reducer 使得状态更新逻辑更加清晰,可以将不同的更新逻辑集中在一个地方,避免了多个 useState 带来的管理混乱。
方便调试reducer 是一个纯函数,给出明确的状态变化规则,便于调试日志记录。
用于复杂状态管理:对于复杂的状态更新,useReducer 是一种优于 useState 的解决方案,尤其是当状态变化需要依赖于多个值时。

缺点:

代码复杂:与 useState 相比,useReducer 需要写更多的代码,尤其是对于简单的状态管理,它的使用可能显得有些过于复杂。
学习成本高:对于 React 新手来说,理解 reducer 函数的工作方式可能需要一些时间,尤其是对于不熟悉 Redux 的开发者。

仅代表个人观点,如有出入欢迎批评指正


原文地址:https://blog.csdn.net/weixin_39593730/article/details/144343150

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!