hook出现的意义

hook是react 16.8版本才增加的知识,它出现的目的就是让我们可以在函数组件中使用很多类组件中才有的特性,例如state、生命周期等。

 

hook简介

hook说白了其实就是一些react中特殊的函数,只不过这些函数允许我们通过钩子的形式钩入一些react的特性,例如我们想要在函数组件中使用state的话就不用将其转为类组件,直接使用useState()这个hook函数即可;如果想要在函数组件中使用类似于类组件的生命周期这些函数的话,直接使用useEffect()这个hook函数……

 

useState Hook

useState()这个hook函数允许我们在函数组件中使用state。

它的使用方法如下:

  1. 引入react中的useState Hook;
  2. 通过调用useState()声明一个state变量和修改这个变量的方法;
  3. 在页面需要的地方渲染这个变量数据,在页面需要更新的地方调用修改变量的方法来更新页面。
import React, { useState } from "react";  //对应第一步

const StateHook = () => {
  const [count, setCount] = useState(0);  //对应第二步

  return (
    <div>
      <p>you click {count} times.</p>  //对应第三步,使用变量
      <button onClick={() => setCount(count + 1)}>click</button>  //对应第三步,修改、更新变量
    </div>
  )
}

export default StateHook;

useState()函数详解:

  • useState()返回一个包含有两个元素的数组,其中数组第一个元素是一个值,第二个元素是一个函数;
  • 在useState()函数左侧通过数组解构赋值的操作,将返回的第一个元素赋值给声明的变量count,将第二个元素赋值给声明的setCount。此处count和setCount的名称是自定义的,可以随便取名;
  • useState()函数只有一个参数,这个参数就是左侧声明的变量的初始值,可以是数值、字符串、对象等;
  • 如果想要定义多个state,只需要多次调用useState()即可。

由上可看出useState Hook跟类组件中定义state、读取state、更新state的区别如下:

1、定义state

useState Hook:

const [count, setCount] = useState(0);

类组件:

constructor(props) {
  super(props);
  this.state = {      
    count: 0    
  };  
}

2、读取state

useState Hook:

<p>you click {count} times.</p>

类组件:

<p>you click {this.state.count} times.</p>

3、更新state

useState Hook:

<button onClick={() => setCount(count + 1)}>click</button>

类组件:

<button onClick={() => this.setState({ count: this.state.count + 1 })}>click</button>

 

useEffect Hook

useEffect()这个hook允许我们在函数组件中使用类似于生命周期这种特性,准确来说,它允许我们在函数组件中执行副作用操作。

它的使用方法如下:

  1. 从react中引入useEffect Hook;
  2. 在函数组件中通过调用useEffect()来执行一个副作用。
import React, { useState, useEffect } from "react";  //对应第一步

const EffectHook = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {  //对应第二步
    document.title = `click ${count} times`;
  })

  return (
    <div>
      <p>you click {count} times.</p>
      <button onClick={() => setCount(count + 1)}>click</button>
    </div>
  )
}

export default EffectHook;

useEffect()函数详解:

  • useEffect()类似于类组件中componentDidMount、componentDidUpdate、componentWillUnmount三个生命周期的结合;
  • useEffect()的传入参数是一个函数,这个函数被称为一个effect,此函数告诉react在第一次DOM渲染和每次更新后应该执行什么副作用,例如数据获取、修改DOM内容等;
  • useEffect()默认情况下在第一次DOM渲染和每次更新后都会执行;
  • 如果想要对一些副作用进行消除,例如取消事件绑定、取消订阅操作等,可以在传入useEffect()的函数中返回一个函数,在这个函数中进行消除副作用的操作,如下:
useEffect(() => {
    //执行副作用
    document.title = `click ${count} times`;
    return () => {
      //消除副作用
      //此处的方法会在组件卸载时执行
      //some code...
    }
})
  • react在每次执行当前effect之前会对上一次的effect进行清除,所以我们可以看到上述代码中消除副作用的函数每次也会执行,但是它内部获取到的count值是上一次的值;
  • useEffect()有第二个可选参数,如果想让当前effect只执行一次,第二个参数传入一个空数组;如果想让当前effect跟随某个state的变化进行执行调用,第二个参数就传入特定的state。

 

Hook使用规则

1、只在最顶层使用hook

  • 不要在循环、条件或嵌套中使用hook

2、只在react函数中调用hook

  • 在react函数组件中调用hook
  • 在自定义hook中调用其他hook

 

自定义hook

自定义hook其实就是一个实现了组件逻辑可重用的函数,只不过这个函数名称必须是以“use”开头而已。

自定义hook一般与我们项目的业务需求关联度比较高,我们可以将组件中可复用的一些逻辑抽离出来,实现一些自定义的hook。

 

其他一些hook

下面是一些在平时开发中使用率较低的hook:

名称

作用

useState

在函数组件中可以使用state。

useEffect

在函数组件中可以使用副作用。

useContext

读取context的值,订阅context的变化。

useReducer

useState的替代方案,跟redux中的reducer类似。

useCallback

缓存函数的引用。

useMemo

缓存函数的值。

useRef

每次渲染时返回同一个ref对象。

useImperativeHandle

可以在使用ref时自定义暴漏给父组件的实例值。

useLayoutEffect

可以用它来获取DOM布局,并同步触发重渲染。

useDebugValue

react开发者工具中显示自定义hook标签。