Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术随笔

    • git教程
    • 前端模块化:CommonJS,AMD,CMD,ES6
    • 如何动态加载本地图片
    • GitHub自动部署脚本
    • React生命周期详解
    • 将父组件的props作为组件的初始state的几种方案
    • webpack基础入门
    • StackOver记录:如何在function中使用redux
    • React中使用onClick时的三种性能优化
    • 思考React状态管理
      • 一、前言
      • 二、常见的几种状态管理方案
        • 1.自定义Hook
        • 2.自定义Hooks+useContext
        • 3.useState与setState的区别
        • 4.useReducer:低成本的数据流
      • 三、总结
      • 参考文章
    • forEach/for..in/of
    • styled-components使用记录
    • 深入理解forEach与forof
    • Node技术架构
    • Redux、Mobx状态管理杂谈
    • JS中的类型检测
    • 如何判断图片是否在可视区域
    • 如何使用图片的懒加载操作
    • JavaScript模块化:从CommonJS到AMD
    • git查看:修改用户名、密码
    • 保持数据Immutable的几种写法
    • 如何实现一个Promise.all
    • resolve(Promise对象)会多出两个微任务
    • todo_基于Mocha的测试驱动开发
    • 浏览器页面渲染机制
    • todo-响应式编程之数据劫持
    • todo-immer库的介绍
    • React-Hooks 基础原理解析
    • JS基本功
    • 函数闭包与this指针
    • 收集 DUMI 配置过程中遇到的问题
    • typescript 类型工具
    • 统一接口的导入导出
    • 网络安全:如何预防 XSS 攻击
    • 浏览器页面渲染机制【2023】
    • 跨域资源请求
    • 浏览器事件循环机制
    • 如何理解浏览器的 user agent 用户代理的含义?
  • 转载文章

  • Mac相关

  • 前端学习周报

  • 包管理工具

  • 技术随笔
  • 技术随笔
wangjiasheng
2021-12-20
目录

思考React状态管理

# 一、前言

目前在项目中有几种状态管理方案:

  1. 自定义Hook
  2. 自定义Hook+useContext
  3. redux与useReducer

# 二、常见的几种状态管理方案

# 1.自定义Hook

在记账项目中,直接使用的自定义useHooks函数,如下:

const useTags = () = >{
  const [tags, setTags] = useState<{ id: number; name: string }[]>([])
	// 增
  const addTag = () => {
    const tagName = window.prompt("请输入tag名称")
    .....
  }
  // 删
  const deleteTag = (id) =>{}
	// 改
  const updateTag = (id, obj) => {}
  // 查
  const findTag = (id) => tags.filter(tag => tag.id === id)[0]
  
  // 自定义导出的函数
  return { tags, addTag, setTags, findTag, updateTag, deleteTag }
}
export { useTags }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在使用的时候:

// 需要运行一下useTags才可以析构出对应的函数和方法
const {tags,addTag} = useTags()
1
2

注意:在一个大型的项目中,需要保证useTags只调用了一次,毕竟它只是一个函数,每次调用都会创建新的state,如果在不同的组件中多次调用这会导致数据不同步。

那么如何做到只调用一次useTags呢,可以使用useContext在最上顶成组件中将useTags执行后返回的对象(操作tags的方法)传递到子组件中即可。

# 2.自定义Hooks+useContext

context.tsx

import {createContext} from 'React'
import {RecordAction} from 'hooks/useRecord' //createContext接受的类型
const ContextReacrd = createContext<RecordAction>({}) 
export default ContextRecord
1
2
3
4

App.tsx

import React from 'react'
import ContextRecord from '/../ContextRecord'
import useRecord from 'hooks/useRecord'
const App = ()=>{
	const recordAction = useRecord() //返回操作record的方法
	return(
    	<ContextRecord.Provider value={recordAction}>
            <Child />
      </ContextRecord.Provider>
    )
}
1
2
3
4
5
6
7
8
9
10
11

这样在后代组件中就可以使用useContext来拿到操作state的函数。

Child.tsx

import React,{useContext} from 'react'
import ContextRecord from '/../ContextRecord'
const Child = ()=>{
	const recordAction = useContext(ContextRecord)//拿到操作record的函数 
    return (
    	<Child2 />
    )
}

export default Child
1
2
3
4
5
6
7
8
9
10

# 3.useState与setState的区别

setState 和 useReducer 的功能很类似,都是状态管理,理论上他们两个的功能是用另一个可以代替的。为什么 React 要提供这样两个功能有重叠的 API 呢?

useState提供了更加细粒度的状态管理。

个类组件只有一个 setState,但是一个函数组件却可以有很多 useState,这让我们可以把独立的状态分开管理,逻辑上更清晰了,更方便维护了,这是 hooks 的天然优势。

# 4.useReducer:低成本的数据流

主要参考文章[3]

简介:简易版Redux

虽说 useReducer 可以拿来做组件内状态管理,但是 useReducer 对于单组件来说太重了,绝大多数情况下是用用不到的。

useReducer 更适合拿来做简单场景下的数据流。useReducer 是阉割版的 redux,只缺了一个状态共享能力,用 hooks 的 useContext 刚刚好。

# 三、总结

项目开发到后期一块很大的维护成本就是大组件,大组件一般都是逻辑复杂、逻辑和 UI 没接耦。React 推荐的开发方式和逻辑和 UI 分离,类组件时期实现的方式是通过 container 管理数据,UI 组件只负责展示,但在紧张的项目迭代中要时刻做到这一点是很麻烦的,原因是类组件承载业务逻辑的最小单元是组件,这个粒度太大了。

Hooks 提供了一种更加自然的方式。因为函数组件本身就是一个返回值比较特殊的函数,函数比类要灵活的多,那我们可以很方便的把某个业务逻辑单独封装在某一个函数中,这种逻辑、UI 接耦的方式简直浑然天成。

这里就要说到 useState 为什么要细粒度的使用,其实从它的 API 也可以看出来,为什么 useState 返回的是一个数组而不是一个对象?因为可以重命名。为什么要重命名?因为需要有明确的语义。什么时候需要明确的语义?当这个值的含义很具体的时候。可以看出 React 希望开发者使用 useState 管理的状态都是原子级的,这样有什么好处呢?为了逻辑解耦啊。否则把一大坨逻辑抽到另一个函数,和放在组件里并没有什么区别。

useState 算是组件内状态管理一个非常优雅的解决方案,但是组件间状态管理的问题还没有解决。Redux 是比较符合 React 理念的数据流管理工具(单向数据流 (opens new window)、易追踪、严格 immutable),而且它和 useContext 结合起来简直就是天衣无缝,React 吸收了 redux 的思想,也算是补齐了在数据流上的能力。

可惜 Redux 适合管理大型应用的复杂数据流,简单场景用着总有点头重脚轻的感觉,useReducer 当然也有同样的问题,他虽然比 redux 轻量,可以做组件内状态管理,但是大多数情况用着会头重脚轻的,除非万不得已,否则我并不想看到 reducer 那坨模板代码。但是拿来做简易的组件间数据流管理就很合适,Hooks 在这点上的能力比类组件要强大很多。

# 参考文章

  1. 掘金:自定义Hook状态管理 (opens new window)
  2. 知乎:useReducer和useContext的结合可以取代Redux么? (opens new window)
  3. 知乎:这一次彻底搞定useReducer-reducer基础篇 (opens new window)
  4. 知乎:总结部分 (opens new window)
编辑 (opens new window)
#React#Redux
上次更新: 2022/04/06, 15:04:00
React中使用onClick时的三种性能优化
forEach/for..in/of

← React中使用onClick时的三种性能优化 forEach/for..in/of→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式