create-react-app 中的Hooks

168 阅读2分钟

React中的Hooks

HookReact v16.8新出的特性,它可以允许我们在不编写class组件的情况下使用state以及其他的React特性。早在之前,React函数组件又称为无状态组件,而有了Hooks之后,函数组件也可以拥有和类组件一样的特性,如组件内的状态,生命周期等。

示例代码如下,useState就是最常用的Hooks之一。

import React, { useState } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

function App() {
  const [num,setNum]= useState(0)
  const handerClick=()=>{
    setNum(state=>state+1)
    setNum(state=>state+1)
    setNum(state=>state+1)
    console.log(num)
  }

  return (
    <>
      {num}
      <button onClick={()=>handerClick()}>+ji</button>
    </>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

点击按钮之后运行结果如下: GIF 2021-12-27 17-33-41.gif 控制台打印出0,3,6,这与页面显示的不一样,说明setNum并不能改变num。页面渲染是在调用setNum之后进行的。

在函数组件中,通过useState实现函数内部维护state,参数state默认的值,返回值为一个数组。第一个值为当前的num,第二个值为更新num的函数setNum

useEffect 也是常用的Hooks之一

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);
 
  useEffect(() => { 
    document.title = `You clicked ${count} times`;
  },[]);
  return (
    <div>
      <p>You clicked {count} times</p >
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect第一个参数接受一个回调函数,默认情况下,即不传第二个参数。useEffect会在第一次渲染和更新之后都会执行,相当于在componentDidMountcomponentDidUpdate两个生命周期函数中执行第一个参数,即回调函数。当传入第二个参数时,只在第二个参数变化时执行回调函数。

与class组件相比

Hooks的使用更加简洁,减少了class组件中的this指向不明确的情况。每调用一次hooks,就会生成一份独立的状态。可是要想实现自己想要的功能,我们也可以自定义hooks

自定义Hooks

上一个例子说到useEffect不传入第二个参数就表示类组件中的componentDidMountcomponentDidUpdate两个生命周期函数,那如何实现componentDidUpdate(即在第一次不更新,后续都更新)呢?一个简单的方法就是使用自定义hooks。

import {useEffect, useRef} from "react";

export const useUpdate=(fn:()=>void,deps:any[])=>{
    const count = useRef(0)
    useEffect(()=>{
        count.current+=1
    })
    useEffect(()=>{
        if(count.current>1){
           fn()
        }
    },deps)
}

useRef是另一个hooksuseRef.current代表一个不随render变化的量。如果把这个量添加到页面上,它在变化时UI不会更新。 Hooks的产生,与React倡导的函数式编程息息相关。