React中的Hooks
Hook是React 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);
点击按钮之后运行结果如下:
控制台打印出
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会在第一次渲染和更新之后都会执行,相当于在componentDidMount和componentDidUpdate两个生命周期函数中执行第一个参数,即回调函数。当传入第二个参数时,只在第二个参数变化时执行回调函数。
与class组件相比
Hooks的使用更加简洁,减少了class组件中的this指向不明确的情况。每调用一次hooks,就会生成一份独立的状态。可是要想实现自己想要的功能,我们也可以自定义hooks。
自定义Hooks
上一个例子说到useEffect不传入第二个参数就表示类组件中的componentDidMount和componentDidUpdate两个生命周期函数,那如何实现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是另一个hooks,useRef.current代表一个不随render变化的量。如果把这个量添加到页面上,它在变化时UI不会更新。
Hooks的产生,与React倡导的函数式编程息息相关。