react hooks渐进式学习

124 阅读3分钟
  1. useEffect的四种玩法

useEffect(callBack):

  1. 第一次渲染完毕后, 执行callback, 等价于类组件的componentDidMount。
  2. 在组件每次更新完毕后,也会执行callback, 等价于componentDidUpdate。

useEffect(callback,[]):

  1. 只有第一次渲染完毕后,才会执行callback, 每一次视图更新完毕后, callback不再执行,类似componentDidMount。
  2. 后面的空数组,无依赖

useEffect(callback,[x]):

  1. 第一次渲染完毕会执行callback。
  2. 后面数组里面如果有变量,变量发生变化的时候,callback会执行。类似于监听。
  3. 后面的数组可以是多个状态,依赖关系,依赖发生变化,callback就会执行,反之,不执行。

useEffect(()=>{return ()=> {}})

callback函数里面又返回一个函数,那么这个函数拿到的状态是上一次执行的值,执行时机是,会在组件释放的时候执行。如果组件更新,会把上一次返回的小函数执行,可以理解为上一次渲染的组件释放了的时候执行。

useEffect不能放在循环、判断操作语句中。 useEffect如果有返回值,那么返回的必须是一个函数,代表组件销毁时触发。

  1. useEffectuseLayoutEffect的区别

如果链表中的callback执行又修改了状态值(视图更新),对于useEffect来讲第一次真是dom已经渲染,组件更新会重新渲染真实的dom, 所以频繁切换的时候,会出现样式内容的闪烁.

对于useLayoutEffect来讲,第一次真实dom还未渲染,遇到callback中修改状态,视图立即更新,创建出新的virtualDOM,然后和上次的virtualDOM合并在一起渲染为真实的dom, 也就是此类需求下,真实dom只渲染一次, 不会出现内容样式的闪烁。

  1. 函数组件中获取ref(前面两种类组件和函数组件都可以,最后一种只能函数组件中使用)
//------方法1
let box = null
<div ref={x => box = x}></div>

//------方法2
let ele = React.createRef()
<div ref={ele}></div>
ele.current //通过current属性获取当前对象

函数组件也有个单独的hooks函数专门用来获取ref的

let box = useRef(null)
<div ref={box}></div>
box.current //通过current属性获取当前对象

React.createRef()useRef(null)区别:

useRef(null) 在组件更新的时候,不会创建新的对象,获取的事第一次创建的那个ref对象

React.createRef()在组件更新的时候会重新创建一个全新的ref对象,比较浪费性能。

在函数组件中推荐useRef,在类组件中使用React.createRef()

子组件是函数组件的时候使用ref需要React.forwardRef()包一层

const Child React.forwardRef(function(props,ref){
   return <div className='child-box' ref={ref}></div>
})

基于forwardRef实现了ref转发的同时,要获取子组件内部的状态和方法就要借助useImperativeHandle来暴露

const Child React.forwardRef(function(props,ref){
   let [text,setText]=useState('hello word')
   useImperativeHandle(ref,()=>{
    return {
      text // 这样父组件就可以用了
    }
   })
   return <div className='child-box' ref={ref}></div>
})
  1. useMemo
let ratio = useMemo(()=>{
 let total =supNum + oppNum
     ratio = '--'
     if(total > 0) ratio = (supNum / total * 100).toFixed(2) + '%'
     ratio
}, [supNum, oppNum])

//当supNum和oppNum发生变化的时候才会执行useMemo的函数

5.useCallback

  1. 组件第一次渲染,useCallback执行,创建一个函数‘callback’,赋值给xxx
  2. 组件后续每一次更新,判断依赖的状态是否改变, 如果改变,则重新创建新的函数堆, 赋值给xxx, 但是如果,依赖的状态没有更新或者没有设置依赖, 则xxx的获取的一直是第一次创建的函数堆,不会创建新的函数出来。或者说基于usecallback,可以始终获取第一次创建函数的内存地址
  3. 父组件嵌套子组件,父组件要把一个内部函数基于属性传递给子组件, 此时传递的这个方法, 我们基于useCallback处理一下会更好。函数子组件就用React.memo(xxx)包裹一下,类子组件就用pureComponent。

6.自定义hooks

  1. 用usexxx开头,react在编译的时候会自动给你做一下校验,不如不能再if中使用use等,所以自定义hooks推荐用use起头命名