文章目录
  1. 1. 简介
  2. 2. 背景
  3. 3. State Hook
    1. 3.1. useState()
    2. 3.2. 对比 Class
    3. 3.3. 使用
  4. 4. Effect Hook
    1. 4.1. useEffect
    2. 4.2. 参数说明
    3. 4.3. 对比Class来理解
      1. 4.3.1. componentDidMount
      2. 4.3.2. componentDidUpdate
      3. 4.3.3. componentWillUnmount
  5. 5. Hook使用规则
  6. 6. 其他

React 16.8新增了Hook特性。本章将讲述Hook的基本用法

简介

React Hook 可以使用户在不用class的情况下,使用React函数,function来进行开发。

本次更新的最大优点是:

No Breaking Changes: 无破坏性改动。也就是说使用Hook并不会破坏React原本的生态。

背景

Hook的优势

  • 使组件之间的状态逻辑可以更方便地复用。例如:如果没有使用store等状态管理框架,那么父子组件之间的状态传递会变得很复杂,如果子组件嵌套层数较多,则会使状态传递变得非常难以维护。
  • 使复杂组件变得容易理解。使用Hook可以将 componentDidMount, componentDidUpdate, componentWillUnmount三者合并为一个方法,并且不需要关心代码逻辑问题。
  • 简化Class,减少开发者在开发过程中,经常遇到this指向问题。

State Hook

State Hook中,我们应该知道一个方法: useState(). 该方法返回了两个参数,并且定义了state的初始值。

useState()

第一个count值是初始状态,第二个值是更新count值的函数,可以理解为this.setState()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React, { useState } from 'react';
const HookState = (props) => {
// useState 返回两个值。 第一个值是当前状态,第二个值是更新当前状态的函数
const [count, changeCount] = useState(0);
return (
<>
<h2>hookState Page</h2>
<div>You clicked this Button {count} times.</div>
<button onClick={()=> {changeCount(count + 1)}}>Click Me to Add!</button>
<button onClick={()=> {changeCount(count - 1)}}>Click Me to Sub!</button>
</>
)
}
export default HookState;

对比 Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React, { Component } from 'react';
class HookState extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
}
this.changeCount = this.changeCount.bind(this)
}
//改变count的值
changeCount(value){
this.setState({
count: value
})
}
render() {
const {count} = this.state;
return (
<>
<h2>hookState Page</h2>
<div>You clicked this Button {count} times.</div>
<button onClick={()=> {this.changeCount(count + 1)}}>Click Me to Add!</button>
<button onClick={()=> {this.changeCount(count - 1)}}>Click Me to Sub!</button>
</>
);
}
}
export default HookState;

对比发现,使用Hook后的代码会非常简洁,而且可读性很高。

使用

useState()可以多次使用,当然了,要避免重复命名的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React, { useState } from 'react';
const HookState = (props) => {
// useState 返回两个值。 第一个值是当前状态,第二个值是更新当前状态的函数
const [count, changeCount] = useState(0);
const [name, changeName] = useState('Bob');
const [age, changeAge] = useState(18);
return (
<>
<h2>hookState Page</h2>
</>
)
}
export default HookState;

Effect Hook

Effect Hook中,我们应该知道一个方法: useEffect().上面的useState代表的是组件的状态,useEffect代表行为。

useEffect

先来看一个全参数的effect方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import React, { useState, useEffect } from 'react';
const HookEffect = (props) => {
const [count, setCount] = useState(0);
const [name, setName] = useState('name');
// 类似于 componentDidMount, componentDidUpdate 和 componentWillUnmount 三个的合并
useEffect(()=>{
// operate
document.title = `${count} Times Clicked`;
console.log("load");
return () => {
console.log('used');
}
},[count])
return (
<>
<h2>hookEffect Page</h2>
<div>You clicked this Button {count} times.</div>
<div>{name}</div>
<button onClick={()=> {setCount(count + 1)}}>Click Me!</button>
</>
)
}
export default HookEffect;

参数说明

调用方式稍微有点绕,但是也比较容易理解。

1
2
3
4
5
6
7
8
9
10
// 组件的每次更新都会调用这个方法
useEffect(()=>{
// 组件第一次加载会调用,之后在count有更新的情况下,都会调用这个方法。
console.log("load");
return () => {
// 组件第一次加载不会调用,之后在count有更新的情况下,在上面的console.log("load")之前调用。可以理解为,卸载之前的执行状态,再执行下一次。该方法可以省略不写,代表每次执行useEffect前,不需要有卸载操作。
console.log('used');
}
// count 表示useEffect方法的执行条件,如果count有更新才会执行内部的方法,否则不会调用。该参数可以省略不写,如果省略不写,则每次组件的更新都会执行useEffect方法。
},[count])

对比Class来理解

componentDidMount

下面我们用useEffect()来实现componentDidMount

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { useState, useEffect } from 'react';
const HookEffect = (props) => {
// useEffect第二个参数传值为空数组,则表示组件第一次加载的时候只触发一次,之后不再触发该useEffect()方法
useEffect(()=>{
console.log('componentDidMount!');
}, []);
return (
<h2>hookEffect Page</h2>
)
}
export default HookEffect;

componentDidUpdate

严格来说,useEffect似乎是摒弃了React生命周期的概念,变成了创建订阅和取消订阅的模式,每一次dom的更新都会触发满足第二个参数条件的useEffect方法。

1
2
3
useEffect(()=>{
console.log('componentDidUpdate');
})

componentWillUnmount

这样理解可能不是太确切,return更像是取消订阅的一种方式,而不完全是componentDidUpdate和componentWillUnmount的集合,因为每次更新dom前,都会先触发return操作。

1
2
3
4
5
6
useEffect(()=>{
console.log('componentDidUpdate');
return ()=>{
console.log('componentWillUnmount');
}
})

Hook使用规则

只在最顶层使用Hook

不要将Hook嵌套在条件语句或循环语句中。确保二次渲染的时候,State或Effect具有第一次渲染后保留的初始值,否则会出现bug或未知问题。

只在React函数中调用Hook

普通的js函数无法使用Hook

其他

常用的Hook就是 useState 和 useEffect 两种,官方还推出了 useContext, useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, useDebugValue 这几种Hook,几乎不太常用,所以暂时可以不关注。

本章完!

文章目录
  1. 1. 简介
  2. 2. 背景
  3. 3. State Hook
    1. 3.1. useState()
    2. 3.2. 对比 Class
    3. 3.3. 使用
  4. 4. Effect Hook
    1. 4.1. useEffect
    2. 4.2. 参数说明
    3. 4.3. 对比Class来理解
      1. 4.3.1. componentDidMount
      2. 4.3.2. componentDidUpdate
      3. 4.3.3. componentWillUnmount
  5. 5. Hook使用规则
  6. 6. 其他