github编辑

React Hook(todo)

React Hook

useRef

作用

useRef返回一个包含current属性的对象,并且改变此对象的值不会导致重新渲染。

useRef通常用于以下三种场景:

  • 保存一个值,以便在下次重新渲染时仍能获取该值

  • 获取DOM节点

  • 避免重新创建引用内容

保存一个值

useRef()保存一个值,并在后面的重新渲染中仍能获取当前的值。

import React, {useState, useRef} from 'react';

export function App(props) {
  const [val,setVal] = useState(0)
  const s = useRef(1)
  const a = {current: 0}

   setInterval(()=>{
     setVal(val+1)
     s.current += 1
     a.current += 1
     console.log(s,a)
   },3000);

  return (
    <div className='App'>
      <div> {val} </div>
    </div>
  );
}

获取DOM节点

如果要获取真实的DOM节点,那么需要:

  1. useRef()初始值设置为null

  2. 将ref对象传递到JSX 节点的ref属性上

  3. ref对象的current属性就指向了该DOM节点,如果节点被删除或不存在,则current为null。

避免重新创建

React 会保存一次初始 ref 值,并在下一次渲染时忽略它。

useMemo

useMemo是一个react Hook,它的作用是在重新渲染时缓存计算结果,来提升性能。

避免昂贵的重新计算

某些时候我们可能会有某个计算量非常庞大的函数,这个函数执行起来非常的慢,理想情况下是将这个计算的结果缓存起来,只有当某些变量改变时才执行函数重新计算,这个时候就可以使用useMemo。这其实和vue的computed相似。

第一种情况,每次组件重新渲染时都会导致slowFunction函数重新计算,但是在第二种情况下,react会缓存slowFunction的计算结果,只有当num改变时,才会重新计算。

useMemo所带来的性能提升可以查看下面示例:

https://codesandbox.io/s/usememobi-mian-ang-gui-de-chong-xin-ji-suan-ilf1dtarrow-up-right

避免子组件重新渲染

当父组件的Props或者state改变时,会导致组件自身和其所有子孙组件都重新渲染,但是有时候我们不需要让子组件重新渲染,这个时候可以使用memo ,通过memo缓存组件,如果该组件的所有Prop都没有改变,则不会重新渲染该组件。

https://codesandbox.io/s/memobi-mian-zu-jian-chong-xin-xuan-ran-ydmlgoarrow-up-right

useCallback

useCallback是一个react Hook,用于在重新渲染期间缓存函数声明。

useCallback需要传递两个参数:一个需要被缓存的函数和一个依赖数组。

react会通过Object.is来比较上一次渲染时的依赖数组的每一项与当前的值是否相同,如果全部相同则会返回上一次的函数,否则useCallback会返回此次渲染的函数。

跳过组件重新渲染

之前说过react可以通过使用memo 来跳过组件重新渲染,以此来优化性能。

只有当组件Child的props有更改的情况下才会重新渲染,否则不会重新渲染组件。

但是有时候memo并不会按照我们想象的情况来工作,当我们传递一个函数作为prop到Child组件时,由于每次App组件重新渲染都会重新执行app组件函数,遇到函数声明或者箭头函数等都会创建一个新的函数,这时memo通过Object.is比较两个函数时会认为prop更改了,就会导致memo优化失效。

这个时候需要利用useCallback缓存函数,将num作为依赖项,只有当num改变时才会重新执行函数声明,创建一个新的函数。

从缓存函数中更新状态

有时,我们可能需要在缓存回调函数中基于之前的值来更新状态。

这看起来和useState更新状态很像,例如:

这也能基于num上一次渲染的值来更新num状态,但是这里的todo却并不是上一次渲染的值,如果我们需要根据上一次渲染的todonum来更新num,我们需要useCallback

https://codesandbox.io/s/usecallbackcong-huan-cun-han-shu-zhong-geng-xin-zhuang-tai-upzqftarrow-up-right

避免Effect频繁执行

以下面的代码为例:

当组件重新渲染后,会声明一个新的createOptions函数,这就导致了useEffect会重复执行。

当然,也可以直接将函数声明放到useEffect中。

useReducer

最后更新于