简介
Hook
是React 16.8
的新增特性。它可以让你在不编写class
的情况下使用state
以及其他的React
特性其实就是专门用于增强函数组件的功能的,使之尽可能的替代类组件而存在
本质上是一个函数
(use...)
,可挂载任何功能仅在函数组件体内生效
State Hook
useState(defaultState);
参数为默认的
state
值返回一个长度为
2
的数组,第一项是state
值,第二项为改变state
值的函数,const [count, setCount] = useState(0);
状态可以有多个
State Hook原理
函数组件的首次调用以及后续更新都会直接调用
use...
函数React
通过函数组件节点的状态表格来保存state
值,使其不会在每次组件函数调用时都会被初始化首次调用函数组件时这些
state
值会被按顺序保存在状态表格中,每个state
值都有一个固定且唯一的下标值,从0
开始更新函数组件时,将会忽略默认
state
值,直接通过对应下标值找到状态表格中所保存的值这也是
React
解释说为什么使用useState
而不是createState
命名的原因
State Hook注意点
useState
不可写在代码块之中,例如判断,循环。因为这可能导致更新函数组件时,一些useState
不被执行之类的混乱情况,从而导致下标值对应错误,state
被赋予不正确的值useState
所返回的第二项函数,引用不会改变,节省内存-
set...
函数的执行会使函数组件重新渲染,也就是再次执行函数若调用改变
state
值的函数set...
时state
的值与之前的完全相同(使用Object.is判断)
,则不会导致重新渲染调用改变
state
值的函数set...
会直接替换原先的值,而不是合并覆盖,所以要注意引用值的使用,可使用...
展开
函数组件内的强制刷新可使用
const [, forceUpdate] = useState({});
forceUpdate({});
调用时发现对象地址不同,则会重新渲染该函数组件如果某些状态之间并没有什么必然的联系,我们应该将他们分开来写,而不是混合到一个
state
中和类组件相同,函数组件中的状态改变若是在
DOM
事件中则是异步的,这种情况下多次调用状态变化函数会被合并来提高效率若是想要在
DOM
事件中多次调用状态变化函数,可以传入一个函数作为参数setCount(prevC => prevC + 1); setCount(prevC => prevC + 1);
这些函数会在
DOM
事件结束时依次执行,前一个函数的返回值作为后一个函数的参数
Effect Hook
用于在函数组件内处理副作用
useEffect()
,该函数接收一个函数参数,函数内部就是我们要执行的副作用代码
副作用
-
ajax
请求,计时器,其他异步操作,更改真实DOM
对象,本地存储,其他会对外部产生影响的操作
Effect Hook注意点
副作用函数
(useEffect的函数参数)
的运行时间点,位于更改了真实DOM
之后,且已经完成重新渲染,也就是用户已经看到了页面变化之后,所以是异步执行,不会阻塞而类组件中的
componentDidMount
以及componentDidUpdate
的执行时间点位于更改了真实DOM
之后,但还未重新渲染,也就是用户还未看到页面变化之前useEffect
在一个函数组件内可多次使用,但不可写入代码块之中,例如判断,循环。与useState
同理副作用函数可以有一个返回值,返回值必须为函数或默认的
undefined
,该函数作用为清理遗留的副作用,例如计时器,运行时间点位于下次副作用函数运行之前,所以首次渲染组件不会运行,useEffect
函数的第二个参数未变化时也不会运行,组件被销毁时一定会运行-
useEffect
函数可接受第二个数组参数,数组中传入该副作用函数内的依赖数据当组件重新渲染后,只有依赖数据与上次不同时,才会再次执行副作用函数
所以若使用空数组作为
useEffect
函数的第二个参数,那么副作用函数仅在首次渲染结束后运行一次,清理函数也仅在卸载时运行一次
副作用函数中,若使用了组件函数
AO
中的变量,则由于闭包的原因,会导致副作用函数中变量不会实时变化,而是使用所在的某次组件函数的调用时的变量
自定义Hook
将一些常用的,多个组件都会使用的
Hook
功能,抽离出去写成一个函数,就叫做自定义Hook
-
组件在使用自定义
Hook
时就等同于将自定义Hook
函数中的代码拿出来放到该自定义Hook
函数执行的地方所以自定义
Hook
中使用set...
同样会使自定义Hook
函数本身以及使用她的函数组件都重新执行一次并且执行顺序也是从函数组件开始,遇到自定义
Hook
执行就进入自定义Hook
函数内部执行,执行结束返回新的值赋值给接收的变量,最后就是函数组件剩余的代码执行
自定义
Hook
必须以use
开头自定义
Hook
中的state
始终是独立的,所以在两个组件中使用相同的Hook
也不会共享state
Context Hook
用于函数组件更轻松的获取
context
-
在消费组件中
const myContext = useContext(MyContext);
Callback Hook
返回一个仅根据依赖项变化而变化地址的函数,常用于给纯组件传递属性方法
Memo Hook
返回第一个函数参数的返回值,仅在依赖项变化时才会再次执行第一个函数参数,返回一个新的值
常用于高开销的计算操作
Ref Hook
让函数组件重新执行时不会又重新创建一个新的
ref
也就是让每个函数组件对象拥有一个固定不变的
ref
通过
.current
来获取,不局限于获取dom
元素或组件对象