React 函数式组件和Hooks

2,452 阅读4分钟

对比类式组件与函数式组件

可以看到最大的区别就是类式组件有this而函数式组件this为undefined,既然是undefined那么就没有什么this.state,this.ref可言。

  • 优点

类式组件可以定义自己的state,用于保存组件内部状态,而函数式组件不可以,因为函数每次调用都会产生新的临时变量。

类式组件有生命周期,可在对应的生命周期完成一定的逻辑,在componentDidMount中发送请求,并且该生命周期只会执行一次,而如果在函数中发送请求,意味着每重新渲染都会发送一次请求。

类式组件改变状态时只会重新执行render函数以及一些生命周期,函数式组件重新渲染时,整个函数都会被重新执行。

  • 缺点

复杂的组件难以理解 拆分class组件比较困难 强行拆分造成过度设计 增加代码复杂度

组件复用状态难,Provider、Consumer共享状态存在很多嵌套,状态复用一般都通过高阶组件。

函数式组件使用props

useState

(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
(2). 语法: const [xxx, setXxx] = React.useState(initValue)  
(3). useState()说明:
        参数: 第一次初始化指定的值在内部作缓存
        返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
(4). setXxx()2种写法:
        setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
        setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值

image.png

useEffect

(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
(2). React中的副作用操作:
        发ajax请求数据获取
        设置订阅 / 启动定时器
        手动更改真实DOM
(3). 语法和说明: 
        useEffect(() => { 
          // 在此可以执行任何带副作用操作
          return () => { // 在组件卸载前执行
            // 在此做一些收尾工作, 比如清除定时器/取消订阅等
          }
        }, [stateValue]) 
        // 如果指定的是[], 回调函数只会在第一次render()后执行 
        //如果不写就检测所有值变化 
        //也可[xxx,yyy]指定检测某值变化 
        //也就是说根据第二个参数决定使用的是componentDidMount钩子还是componentDidUpdate钩子
    
(4). 可以把 useEffect Hook 看做如下三个函数的组合
        componentDidMount()
        componentDidUpdate()
    	componentWillUnmount() 

image.png

useContext

回顾之前使用context

image.png

使用useContext

image.png

useReducer

  • useReducer仅仅是useState的一种替换方案,在某些场景下,如果state的处理逻辑比较复杂,可以通过 useReducer来对其进行拆分。

  • 或者这次修改的state需要依赖之前的state时,也可以使用。

image.png

useCallback(针对函数)

image.png

image.png

  • 把内联回调函数及依赖项数组作为参数传⼊ useCallback ,它将返回该回调函数的 memoized 版本,该回调函数仅在某个依赖项改变时才会更新。当你把回调函数传递给经过优化的并使⽤引⽤相等性去避免⾮必要渲染(例如 shouldComponentUpdate )的⼦组件时,它将⾮常有⽤。

  • 使用场景:将一个组件中的函数,传递给子组件进行回调使用时,使用UseCallback对函数进行处理进行性能优化。

useMemo(针对返回值)

复杂计算的应用

传递子组件引用类型

image.png

image.png

  • 把“创建”函数和依赖项数组作为参数传⼊ useMemo ,它仅会在某个依赖项改变时才重新计算memoized 值。这种优化有助于避免在每次渲染时都进⾏⾼开销的计算。

useRef

(1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
(2). 语法: const refContainer = useRef()
(3). 作用:保存标签对象,功能与React.createRef()一样

image.png

useImperativeHandle

image.png

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle 应当与 forwardRef 一起使用。

useLayoutEffect

useLayoutEffect与useEffect只有一点区别:

  • useEffect会在渲染的内容更新到DOM上后执行,不会阻塞DOM的更新。

  • useLayoutEffect会在渲染的内容更新到DOM上之前执行,会阻塞DOM的更新。

  • 如果我们希望在某些操作发生之后再更新DOM,那么应该将这个操作放到useLayoutEffect。

自定义Hooks

image.png image.png

(1). 自定义Hooks是一个函数
(2). 其名称以use开头
(3). 函数内部可以调用其它的Hooks
(4). 只能在函数最外层调用Hooks,不要在循环、条件判断或者子函数中调用
(5). 只能在React的函数式组件中调用Hook,不要在其他js函数中调用。

image.png