1. 为什么要Hooks?
有了hooks,就可以不用class了,所有的组件都可以是function,hooks让function无状态组件有了状态。
class 带来的麻烦
用class创建react组件时,this指向是一件很棘手的事情,为了保证this指向正确,我们经常需要写:
this.handleClick = this.handleClick.bind(this),或者是:
<button onClick = {() => this.handleClick(e)>。
2. State Hooks
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
声明状态变量
const [count, setCount] = useState(0);
useState函数接收的参数是状态初始值(initial state),它返回一个数组,数组第[0]项是当前状态值,第[1]项是可以改变状态值的函数。
也就是声明了一个状态变量count,把它的初始值设为0,同时提供了一个可以更改count的函数setCount。
假如一个组件有多个状态
useState可以多次调用
function ExampleWithManyStates() {
const [age, setAge] = useState(42);
const [fruit, setFruit] = useState('banana');
const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
- useState的初始值可以多样
useState接收的初始值没有规定一定要是string/number/boolean这种简单数据类型,它完全可以接收对象或者数组作为参数。
react 怎么保证多个useState相互独立?
答案是,react是根据useState出现的顺序来定的。
2. Effect Hook
我们写的有状态组件,通常会产生很多的副作用(side effect),比如发起ajax请求获取数据,添加一些监听的注册和取消注册,手动修改dom等等。
我们之前都把这些副作用的函数写在生命周期函数钩子里,比如componentDidMount,componentDidUpdate和componentWillUnmount。而现在的useEffect就相当与这些声明周期函数钩子的集合体。
useEffect 解绑一些副作用
当我们在componentDidMount里添加了一个注册,我们得马上在componentWillUnmount中,也就是组件被注销之前清除掉我们添加的注册,否则内存泄漏的问题就出现了。
import { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// 一定注意下这个顺序:告诉react在下次重新渲染组件之后,同时是下次调用ChatAPI.subscribeToFriendStatus之前执行cleanup
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
这种解绑的模式跟componentWillUnmount不一样。
componentWillUnmount只会在组件被销毁前执行一次而已,而useEffect里的函数,每次组件渲染后都会执行一遍,包括副作用函数返回的这个清理函数也会重新执行一遍。
按照以前,如果props.friend.id变了,就要添加componentDidUpdate来处理。
useEffect没有这个问题:
1.页面首次渲染
2.替friend.id=1的朋友注册
3.突然friend.id变成了2
4.页面重新渲染
5.清除friend.id=1的绑定
6.替friend.id=2的朋友注册
...