只在最顶层使用Hook,不在条件、循环或者嵌套函数中使用Hook
只在React函数式组件或自定义Hook中使用Hook
Hook存储在组件的私有属性中__hooks_list数组中。读取和存储都依赖currentIndex,如果hook的执行顺序改变,currentIndex获取的hook可能是完成错误的。

Effect Hook 可以在函数组件中执行一些具有side effect(副作用)的操作
回调函数: 在组件第一次render和之后的每次update后运行,React保证在DOM已经更新完成后才会回调。
状态依赖(数组): 当配置了状态依赖项后,只有检测倒配置状态变化后,才会调用回调函数。
useEffect的第一个参数可以返回一个函数,这个函数会在页面更新渲染后,执行下次useEffect之前调用。这个函数是对上一次调用useEffect进行清理。
执行上面的代码,并点击几次按钮,会得到下面的结果:
如果加上浏览渲染的情况,结果应该是这样的:
那为什么浏览器在渲染完后,再执行清理的方法还能找到上一次的state呢?原因很简单,我们再useEffect中返回的是一个函数,形成了一个闭包,这能保证我们上一次执行函数存储的变量不会被销毁和污染。
举例会更好理解:
componentDidMount等价于useEffect的回调,仅在页面初始化完成后执行一次。当useEffect的第二个参数传入一个空数组时就可以实现这种效果。
官方不推荐这种写法,因为可能会导致一些错误。
不像componentDidMount或者componentDidUpdate,useEffect中使用的effect并不会阻止浏览器渲染页面。这让页面渲染看起来更加流程。
红圈中是同步操作
useLayoutEffect和useEffect类似,但不同的是:
useEffect不会阻塞浏览器的重绘
useLayoutEffect会阻塞浏览器的重绘。如果需要手动修改dom,推荐使用useLayoutEffect。因为如果在useEffect中更新dom,useEffect不会阻塞浏览器重绘,用户可能会看到因为更新导致的闪烁。
使用useRef Hook,你可以轻松获取dom的ref。
useRef不仅仅可以用来当作获取dom的ref。还可以通过useRef产生的ref的current属性的可变性,用它来保存任意值。
componentDidUpdate就相当于第一次调用的useEffect,借助useRef生成一个标识,来记录是否为第一次执行:
在React中,性能优化点在于:
调用setState,就会触发组件的重新渲染,不论state是否变化
父组件更新,子组件也会更新
基于以上两点,useCallback和useMemo就是解决性能问题的杀手锏。
useCallback和useMemo的异同:
共同点:
仅仅是依赖数据发生变化时,才会重新计算结果,起到缓存作用。
两者区别:
useMemo计算结果是return回来的值,主要用于缓存计算结果的值。应用场景: 需要计算的状态。
useCallback计算结果是函数,主要用于缓存函数。
useCallback返回的是缓存的函数,最简单的用法:
const fnA = useCallback(fnB, [a]);
当依赖 a 变更时,会返回新的函数。我们无法很好的判断返回函数是否变更,可以借助ES6新增的数据类型Set来判断,具体如下:
每次修改count,set.size都会+1,这说明useCallback依赖变量count变化时,会返回新的函数。而val变化时,set.size无变化,说明返回的是缓存的函数。
知道useCallback特点后,有什么作用呢?
使用场景:有一个父组件,包含子组件,子组件接收一个函数作为peops。通常而言,如果父组件更新了,子组件也会执行。但大多数情况下,更新是没有必要的。我们可以借助useCallback来返回函数,然后把这个函数作为props传递给子组件;这样,子组件就能避免不必要的更新。
我们先来看个反例:
这里创建了两个state,然后通过expensive函数,执行一次昂贵的计算,拿到count对应的某个值。我们可以看到:无论是修改count还是val,由于组件的重新渲染,都会触发expensive的执行。但是这里的昂贵计算只依赖于count的值,在val修改的时候,是没有必要再次计算的。
在这种情况下,我们就可以使用useMemo,只在count的值修改时,执行expensive计算:
上面我们可以看到,使用useMemo来执行昂贵的计算,然后将计算值返回,并且将count作为依赖值传递进去。这样,就只会在count改变的时候触发expensive执行,在修改val的时候,返回上一次缓存的值。
同时也可以用来持久化一个执行函数,避免子组件的重复渲染,例如: