React学习笔记(HOOK篇)
useState
示例:
import React, { useState } from 'react';
function Example() {
// 声明一个叫 “count” 的 state 变量。
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
export defualt Example;
此种写法转换成class组件为:
import React, {Component} from "react";
class UnHookExample extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleClick = this.handleClick.bind(this);
}
handleClick () {
this.setState(
{count:this.state.count+1}
);
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={this.handleClick}>
Click me
</button>
</div>
);
}
}
export default UnHookExample;
区别于this.setStatus
的方法,hook使用const [count, setCount] = useState(0);
的写法,优势在于不需要考虑this绑定问题(关于this绑定问题在基础篇中提过),也不需要在调用时需要写成 this.state.count
.
useEffect
它跟 class 组件中的 componentDidMount
、componentDidUpdate
和 componentWillUnmount
具有相同的用途,只不过被合并成了一个 API,当你调用 useEffect
时,就是在告诉 React 在完成对 DOM 的更改后运行“useEffect”函数。
个人理解就是:useEffect函数,在1.render内容第一次渲染完成后调用(组件挂载),2.更新时也调用,3.在组件卸载时,这三个时间会被调用,但是需要注意,组件卸载时调用的是useEffect函数里 return function cleanup(){}
return的函数,挂载和更新时调用没有return的函数,示例如下:
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
Hook 使用规则
Hook 就是 JavaScript 函数,但是使用它们会有两个额外的规则:
- 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
- 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
自定义Hook
Hook本身就是一个js函数,因此如果两个组件有相同的方法需要使用,那么我们就可以把这个方法以Hook的方式封装起来并交给他们调用。
具体示例:
- 首先我们有两个组件,其中大部分方法是完全一样的,只是根据不同的结果返回不同元素
//组件一
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
组件一 展示在线状态'Online' : 'Offline';
import React, { useState, useEffect } from 'react';
function FriendListItem(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
组件二 展示在线状态的颜色'green' : 'black';
但是组件一和组件二所用的判断方法完全一致,此时便可以把方法提取出来变成一个Hook使用,具体如下:
- Hook
import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
- 组件一调用新定义的Hook
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
- 组件一调用新定义的Hook
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id);
return (
<li style={{ color: isOnline ? 'green' : 'black' }}>
{props.friend.name}
</li>
);
}
注意:
Hook的名字应该始终以 use
开头,这样可以一眼看出其符合 Hook 的规则。
其他HookApi
用到再看