React Hooks自定义hooks

1,796 阅读2分钟

本文转载自玩转react-hooks,自定义hooks设计模式及其实战

什么是自定义hooks

自定义hooks是在react-hooks基础上的一个拓展,可以根据业务需要制定满足业务需要的hooks,更注重的是逻辑单元。通过业务场景不同,我们到底需要react-hooks做什么,怎么样把一段逻辑封装起来,做到复用,这是自定义hooks产生的初衷。

如何设计一个自定义hooks,设计规范

逻辑+ 组件

image.png

自定义 hooks 专注的就是逻辑复用。将一段通用的逻辑存封起来,当需要这个逻辑的时候,开箱即用。

自定义hooks-驱动条件

hooks本质上是一个函数。函数的执行,决定无状态组件组件自身的执行上下文。每次函数的执行(本质上就是组件的更新)就会执行自定义hooks的执行,由此可见组件本身执行和hooks的执行如出一辙。

那么prop的修改,useState,useReducer使用是无状态组件更新条件,也就是驱动hooks执行的条件。

image.png

自定义hooks-通用模式

我们设计的自定义react-hooks应该是长的这样的。传入参数,返回我们想要的内容。

image.png

const [ xxx , ... ] = useXXX(参数A,参数B...)

自定义hooks-条件限定

如果自定义hooks没有设计好,比如返回一个改变state的函数,但是没有加条件限定,就有可能造成不必要的上下文的执行,更有甚的是组件的循环渲染执行。

比如:我们写一个非常简单hooks来格式化数组将小写转成大写。


import React , { useState } from 'react'
/* 自定义hooks 用于格式化数组将小写转成大写 */
function useFormatList(list){
   return list.map(item => {
       console.log(1111)
       return item.toUpperCase()
   })
}
/* 父组件传过来的list = [ 'aaa' , 'bbb' , 'ccc'  ] */
function Index({ list }){
   const [ number, setNumber ] = useState(0);
   const newList = useFormatList(list);
   return <div>
       <div className="list" >
          { newList.map(item => <div key={item}>{ item }</div>) }
        </div>
        <div className="number">
            <div>{ number }</div>
            <button onClick={()=> setNumber(number + 1) } >add</button>
        </div>
   </div>
}
export default Index

1.gif

如上述问题,我们格式化父组件传递过来的list数组,并将小写变成大写,但是当我们点击add时,Index函数会重新执行一遍,useFormatList自定义hooks也会执行。理想状态下数组不需要重新format,但是实际跟着执行format。无疑增加了性能开销。

所以我们在设置自定义hooks的时候,一定要把条件限定-性能开销加进去

于是乎我们这样处理一下,返回处理过的list用useMemo函数包起来,就解决了每次都会执行list.map的问题。

function useFormatList(list) {
    return useMemo(() => list.map(item => {
        console.log(1111)
        return item.toUpperCase()
    }), [])
}

参考文章

玩转react-hooks,自定义hooks设计模式及其实战

「react进阶」一文吃透react-hooks原理

「react进阶」年终送给react开发者的八条优化建议(篇幅较长,占用20-30分钟)