Brief Intro: Discuss some React Hooks usage and features
- useState
- useEffect
- useLayoutEffect
- useRef
- useMemo
前言
React 的渲染主要经历了三个阶段:
- 渲染:创建 react 元素;
- 调和:主要进行 react 虚拟 dom 对比;
- 提交:更新 dom 元素
触发渲染的几种情况
- 组件收到新状态;
- 组件内部状态被更新;
- 上下文值发生改变(useConttext 监听变化)
- 父组件因为上述原因发生重新渲染
useState
[state,setState] = useState(initial)
- 返回一个状态值和更新状态的函数,默认值为 useState (xxx) 的入参
- 组件内部可以接收多个 useState,setState 为异步方法,不会进行对象合并
- 调用更新状态函数的时候,原来的状态会保留在存储器中,新状态并在重新渲染的时候返回,即该函数的调用会触发组件重新渲染
- 如果被多次调用,react 底层会进行合并处理,只触发一次重新渲染
useEffect
1 | useEffect(() => { |
- 不写依赖:组件更新就会执行副作用函数;
- 依赖参数为 []:组件生命周期进入后只会执行一次,即 didMount;
- 存在依赖:当依赖变动的时候,钩子函数内部的副作用函数会重新执行,即 didUpdate;
- return 函数:代表组件销毁的时候执行组件卸载时的相关操作,仅当依赖项为空时;
执行时机
useEffect 的执行是在 commit
之后,即在页面已经渲染完成之后再触发
执行顺序
父子组件同时存在 useEffect 的时候,子组件的 useEffect 先走
- 父组件进入 commit 阶段,发现有 Son 组件需要渲染。
- 开始进行 Son 的生命周期,Son 进入 commit 阶段,执行子组件的 useEffect,Son 渲染结束
- 父组件进行 commit 阶段,渲染完成,执行 useEffect
优点与不足
- 优点:不会阻塞浏览器渲染更新
- 缺点:会造成二次污染,用户体验不佳
useLayoutEffect
与 componentDidMount 同步执行,在 commit
阶段之前执行,执行顺序优于 useEffect
优点与不足
优点:
- 与 componentDidMount 同步执行,不会造成二次污染
- useLayoutEffect 是在 DOM 更新之后,浏览器绘制之前,这样可以方便修改 DOM,获取 DOM 信息,这样浏览器只会绘制一次,如果修改 DOM 布局放在 useEffect ,那 useEffect 执行是在浏览器绘制视图之后,接下来又改 DOM ,就可能会导致浏览器再次回流和重绘。而且由于两次绘制,视图上可能会造成闪现突兀的效果。
缺点:可能会阻塞浏览器屏幕的渲染更新
useRef
- useRef 是一个对象,它拥有一个 current 属性,并且不管函数组件执行多少次,而 useRef 返回的对象永远都是原来那一个
- 修改 ref 的值是不会引发组件的重新 render ,而 createRef 每次都会发生变化
createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用。
useMemo
const cacheSomething = useMemo(create,deps)
- create:第一个参数为一个函数,函数的返回值作为缓存值,如上 demo 中把 Children 对应的 element 对象,缓存起来。
- deps: 第二个参数为一个数组,存放当前 useMemo 的依赖项,在函数组件下一次执行的时候,会对比 deps 依赖项里面的状态,是否有改变,如果有改变重新执行 create ,得到新的缓存值。
- cacheSomething:返回值,执行 create 的返回值。如果 deps 中有依赖项改变,返回的重新执行 create 产生的值,否则取上一次缓存值。
原有的 hooks 存在闭包问题,因此引入新的 hooks 弥补缺陷 (提议)
useEvent (封装事件处理函数–useCallback)
在组件多次 render 的时候保持一致
函数内始终能够获取到最新的 props 和 state