【React入门总结05】react hooks

62 阅读5分钟

react官网链接 : zh-hans.react.dev/ ;

什么是Hooks?

它可以让我们在不编写class的情况下使用state以及其他的React特性;

Hook的出现基本可以代替我们之前所有使用class组件的地方;

但是如果是一个旧的项目,你并不需要直接将所有的代码重构为Hooks,因为它完全向下兼容,你可以渐进式的来使用它;
Hook只能在函数组件中使用,不能在类组件,或者函数组件之外的地方使用;

下面介绍常见的几个hooks用法。

1.useState

useState会帮助我们定义一个 state变量,useState 是一种新方法,它与 class 里面的 this.state 提供的功能完全相同。
一般来说,在函数退出后变量就会”消失”,而 state 中的变量会被 React 保留。
useState接受唯一一个参数,在第一次组件被调用时使用来作为初始化值。(如果没有传递参数,那么初始化值为undefined)。
useState的返回值是一个数组,我们可以通过数组的解构,来完成赋值会非常方便。

image.png

2.useEffect

Effect Hook 可以让你来完成一些类似于class中生命周期的功能

通过useEffect的Hook,可以告诉React需要在渲染后执行某些操作;
useEffect要求我们传入一个回调函数,在React执行完更新DOM操作之后,就会回调这个函数;
默认情况下,无论是第一次渲染之后,还是每次更新之后,都会执行这个 回调函数;

并且使用Effect Hook,可以根据功能书写多个useEffect,React 将按照 effect 声明的顺序依次调用组件中的每一个 effect;

image.png 在class组件的编写过程中,某些副作用的代码,我们需要在componentWillUnmount中进行清除, 那么Effect Hook通过什么方式来模拟componentWillUnmount呢 useEffect传入的回调函数A本身可以有一个返回值,这个返回值是另外一个回调函数B,该函数可以称为清除函数  会在组件更新和卸载的时候执行清除操作;正如之前学到的,effect 在每次渲染的时候都会执行;

image.png 但是如果每次渲染时都重新执行useEffect这会导致两个问题:
某些代码我们只是希望执行一次即可,类似于componentDidMount和componentWillUnmount中完成的事情; 另外,多次执行也会导致一定的性能问题; 那么我们如何控制useEffect的执行与不执行呢 这时候需要用到UseEffect的第二个参数(它表示受谁的影响) 通过一个简单demo,观察控制台输出,可得出如下总结:

1.effect没有第二个依赖项,每次更新都会执行

2.依赖项为空数组,只会在第一次渲染和销毁的时候执行

3.依赖项拥有具体的依赖项时,只有当依赖项发生变化,才会重新执行effect函数

image.png

3.useCallback

useCallback实际的目的是为了进行性能的优化。
如何进行性能的优化呢? useCallback会返回一个函数的 memoized(记忆的) 值;
在依赖不变的情况下,多次定义的时候,返回的值是相同的; 通常使用useCallback的目的是不希望子组件进行多次渲染,并不是为了函数进行缓存;

情况一:直接将普通函数传递给子组件 从控制台的输出可以看到,当修改message的值时,函数由于组件的重新渲染重新定义,造成了子组件的重新渲染

image.png 但是从代码中可以看出,这个函数只处理了couter的逻辑,那么当message改变时,子组件不应该被重新渲染。 这时就可以使用useCallback将函数包裹起来传递给子组件,并且传入依赖项,表示当依赖项变化时,会重新定义。 可以发现,当message变化时,子组件并没有重新渲染,当count变化时,函数才会被重新定义。(依赖项不传时,会造成问题,只记录第一次的值)

image.png

4.useMemo

useMemo实际的目的也是为了进行性能的优化。
useMemo返回的也是一个 memoized(记忆的) 值;

在依赖不变的情况下,多次定义的时候,返回的值是相同的;

它的优化点主要有两个:

1.大量不需要重复操作的复杂计算

直接计算,重新渲染,每次都会执行

image.png

当使用了useMemo包裹时,计算过程不会反复被执行。 不过需要执行的是,要传递第二个参数,否则并不会被记忆

image.png

2.当给子组件传递相同内容的对象

直接传递

image.png 使用useMemo包裹,这时并没有造成子组件的重复渲染。

image.png

5.useRef

useRef返回一个ref对象,返回的ref对象再组件的整个生命周期保持不变。

常见的用法有两个:

用法一:引入DOM(或者组件,但是需要是class组件)元素;

image.png

用法二:保存一个数据,这个对象在整个生命周期中可以保存不变;

image.png

6.useContext

 类组件可以通过 类名.contextType = MyContext方式,在类中获取context;
多个Context或者在函数式组件中通过 MyContext.Consumer 方式共享context;
但是多个Context共享时的方式会存在大量的嵌套:
Context Hook允许我们通过Hook来直接获取某个Context的值;

image.png

image.png

7.redux hooks(在redux章节会提到)

8.router hooks (在router章节会提到)