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() {}语句,
b、taskReducer
函数中设计了新增、删除、修改三个类型;
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 的开发者。
仅代表个人观点,如有出入欢迎批评指正