深入理解React – 4 – Hooks

React Hooks

我们知道从React16以来React官方团队引入了新的组件书写方式,即Function Components,从Class Components 过渡到Function Components, 从两者兼容,到鼓励大家使用Function Components这中间发生了什么呢? 我们一起来看一下吧。

Question: 为什么要从Class Components过渡到Function Components呢?

第一点就是组件的复用更容易了,React在引入Function Component的同时也引入了React Hooks这一概念,我们可以通过编写自定义Hook 来代替原来的HOC或者Render Props。 自定义hooks更加易于理解,也对我们研发人员更友好

第二点class components的this指向问题,在class组件中,一些改变DOM的操作,虽然props是不变的,但是this的指向是有可能发生改变的,如果this上的数据被修改可能造成意想不到的变化,例如用setTimeout延迟渲染,等待的过程中就有可能打破this.props和渲染之间的关联。 而在函数组件中每一次调用都是传入参数做新的调用,不会影响上一次操作对DOM的捕获

那么我们再详细聊一下React Hooks吧

常用的React Hooks包括useEffect, useState, useRef, useCallback, useMemo等

useEffect

// first代码块执行需要处理的副作用,执行的时机由third这个依赖项决定
// second代码块执行当前组件卸载时需要的操作,例如卸载监听事件等。
useEffect(() => {
      // first
    
      return () => {
        //second
      }
    }, [third])

因为在函数组件中我们不能再使用生命周期的方法了,因此React团队引入了useEffect用来处理组件的副作用(side effects)。

说到副作用,一般认为脱离了React作用范围的功能都叫做side effects, 例如webStorage的操作, fetch data等。

常用的生命周期componentDidMount, componentDidUpdate, componentWillUnmount都可以用useEffect代替,但官方并不鼓励我们用useEffect时去思考代替原来的生命周期,因为useEffect是一种完全不同的设计模式,他的出现就是为了处理副作用。

useState

用来在函数组件中设置和更新变量

// 初始化点击数为0,通过setCount更新点击数,调用是使用count
const [count, setCount] = useState(0)

useRef

useRef用来操作DOM,需要先做好绑定操作,常用来制作动画效果

useCallback (性能优化)

React在重新渲染组件时需要重新渲染组件和方法,因此在复杂应用需要同时处理上百个组件的情况就会造成很大的开销。因为方法造成的开销更大,因此React引入了useCallback这一个hook,useCallback会缓存方法,注意并不是缓存方法执行的结果,他会在参数没有变化时返回原有的方法。他和useEffect一样,需要指定一个以来的数组,在数组没有变化时不再重新初始化这个方法。dependency对比是用Object.is做对比的(==会转换对比的类型;===对比+0和-0会返回true,Object.is返回false; ===对比两个NaN会返回false, Object.is会返回true)

useMemo(性能优化)

同样是性能优化的常用手段,useMemo是存储计算的结果,只有在依赖数组发生变化时才会重新计算

React Hooks的使用原则

  1. 只在React函数中调用hooks
  2. 不要在循环,条件或者嵌套语句中是用hooks

这是因为hooks需要严格确保执行的顺序,因为hooks的运作在底层依赖于顺序链表,以useState为例

首次渲染时走的是mountState链路,更新state时走的是updateState链路,因此如果两次链表不同,那么渲染的结果就是不可控的了。


Posted

in

by

Tags: