本文对 16.8 版本之后 React 发布的新特性 Hooks 进行了详细讲解,并对一些常用的 Hooks 进行代码演示,希望可以对需要的朋友提供点帮助。
Hooks
是 React v16.7.0-alpha
中加入的新特性。它可以让你在 class
以外使用 state
和其他 React
特性。
本文就是演示各种 Hooks API 的使用方式,对于内部的原理这里就不做详细说明。
Example.js
import React, {
useState } from 'react';
function Example() {
// 声明一个名为“count”的新状态变量
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {
count} times</p>
<button onClick={
() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Example;
useState
就是一个 Hook
,可以在我们不使用 class
组件的情况下,拥有自身的 state
,并且可以通过修改 state
来控制 UI 的展示。
const [state, setState] = useState(initialState)
initialState
,可以是数字,字符串等,也可以是对象或者数组。state
变量,setState
修改 state值的方法。setState
的异同点:onClick
事件中,调用两次 setState
,数据只改变一次。setState
是合并,而函数组件中的 setState
是替换。之前想要使用组件内部的状态,必须使用 class 组件,例如:
Example.js
import React, {
Component } from 'react';
export default class Example extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {
this.state.count} times</p>
<button onClick={
() => this.setState({
count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
而现在,我们使用函数式组件也可以实现一样的功能了。也就意味着函数式组件内部也可以使用 state 了。
Example.js
import React, {
useState } from 'react';
function Example() {
// 声明一个名为“count”的新状态变量
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {
count} times</p>
<button onClick={
() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export default Example;
创建初始状态是比较昂贵的,所以我们可以在使用 useState
API 时,传入一个函数,就可以避免重新创建忽略的初始状态。
普通的方式:
// 直接传入一个值,在每次 render 时都会执行 createRows 函数获取返回值
const [rows, setRows] = useState(createRows(props.count));
优化后的方式(推荐):
// createRows 只会被执行一次
const [rows, setRows] = useState(() => createRows(props.count));
之前很多具有副作用的操作,例如网络请求,修改 UI 等,一般都是在 class
组件的 componentDidMount
或者 componentDidUpdate
等生命周期中进行操作。而在函数组件中是没有这些生命周期的概念的,只能 return
想要渲染的元素。
但是现在,在函数组件中也有执行副作用操作的地方了,就是使用 useEffect
函数。
useEffect(() => { doSomething });
两个参数:
第一个是一个函数,是在第一次渲染以及之后更新渲染之后会进行的副作用。
第二个参数是可选的,是一个数组,数组中存放的是第一个函数中使用的某些副作用属性。用来优化 useEffect
虽然传递 [] 更接近熟悉的
componentDidMount
和componentWillUnmount
执行规则,但我们建议不要将它作为一种习惯,因为它经常会导致错误。
假如此时我们有一个需求,让 document 的 title 与 Example 中的 count 次数保持一致。
使用 class 组件:
Example.js
import React, {
Component } from 'react';
export default class Example extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${
this.state.count } times`;
}
componentDidUpdate() {
document.title = `You clicked ${
this.state.count } times`;
}
render() {
return (
<div>
<p>You clicked {
this.state.count} times</p>
<button onClick={
() => this.setState({
count: this.state.count