Class组件的问题
- 大型组件很难拆分和重构,很难测试(即class不易拆分)
- 相同业务逻辑,分散到各个方法中,逻辑混乱
- 复用逻辑变得复杂,如HOC、Render Prop
State Hook
函数组件是一个纯函数,执行完即销毁,无法存储state,需要State Hook,即把state功能”钩“到纯函数中
Effect Hook
1 | import React, { useState, useEffect } from 'react' |
*所有的定时任务或全局事件绑定,一定要在组件销毁时,清除定时任务或解绑全局事件,防止内存泄漏
1 | // demo |
useEffect让纯函数有了副作用
- 默认情况下,执行纯函数,输入参数,返回结果,无副作用
- 所谓副作用,就是对函数之外造成影响,如设置全局定时任务
- 而组件需要副作用,所以有需要useEffect”钩“到纯函数中
useEffect中返回函数callbackFn
- useEffect依赖[],组件销毁时执行fn,等同于WillUnmount
- useEffect无依赖或依赖[a, b],组件更新时执行fn
- 即,下一次执行useEffect之前,就会执行fn,无论更新或卸载
1 | // demo |
useRef 使用
1 | // demo |
useContext 使用
1 | // demo 主题颜色传递 |
useReducer 使用
1 | // demo |
useReducer和redux的区别
- useReducer是useState的代替方案,用于state复杂变化
- useReducer是单个组件状态管理,组件通讯还需要props
- redux是全局状态管理,多组件共享数据
useMemo 使用
1 | // demo |
useMemo总结
- React默认会更新所有子组件
- class组件使用shouldComponentUpdate和PureComponent做优化
- Hooks中使用useMemo,但优化的原理是相同的,子组件需要用memo函数封装
useCallback使用
1 | // demo |
useCallback总结
- useMemo缓存数据
- useCallback缓存函数
- 两者都是React Hooks的常见优化策略
自定义 Hook
1 | // demo |
自定义Hook总结
- 本质是一个函数,以use开头(重要)
- 内部正常使用useState,useEffect或者其他Hooks
- 自定义返回结果,格式不限
第三方Hooks
Hooks使用规范
只能用于React函数组件和自定义Hook中,其他地方不可以;
只能用于顶层代码,不能在循环、判断中使用Hooks;
eslint插件eslint-plugin-react-hooks可以帮助你,(CRA脚手架是有配置的);
1
2
3
4
5
6
7
8
9
10
11
12
13// ESLint 配置文件
// eslint-plugin-react-hooks
{
"plugins": [
// ...此处省略 N 行...
"react-hooks"
],
"rules": {
// ...此处省略 N 行...
"react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
"react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
}
}
关于Hooks调用顺序
1 | // demo |
Hooks调用顺序必须保持一致
- 无论是render还是re-render,Hooks调用顺序必须一致
- 如果Hooks出现在循环、判断里,则无法保证顺序一致
- Hooks严重依赖于调用顺序!重要!
class组件逻辑复用
- 高阶组价HOC
- 组件层级嵌套过多,不易渲染,不易调试;
- HOC会劫持props,必须严格规范,容易出现疏漏;
- Render Prop
- 学习成本高,不易理解;
- 只能传递纯函数,而默认情况下纯函数功能有限;
- Mixins早已废弃
- 变量作用域来源不清;
- 属性重名;
- Mixins引入过多会导致顺序冲突;
Hooks组件逻辑复用好处
- 完全符合Hooks原有规则,没有其他要求,易理解记忆
- 变量作用域明确
- 不会产生组件嵌套
React Hooks注意事项(坑点)
- useState初始化值,只有第一次有效
1 | // demo |
- useEffect内部不能修改state
1 | // demo |
- useEffect可能出现死循环,useEffect第二个参数不能依赖引用类型,如Object,Array等,否则会出现死循环
1 | // demo |