Introduction
Hook is a new feature of React 16.8. It allows you to write without class
the use of the case state
as well as other characteristics of React.
reason
The original intention of Hook is to solve the original stateless structure that requires the use of state, which must be transformed into the pain point of class.
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>
);
}
This is the simplest example provided by the official. It is not difficult to understand that the button will be called once every time it is clicked setCount
, so that the changed count
value is equivalent to the following example.
class Example extends React.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>
);
}
}
I use comments to explain that I may better understand the meaning of each parameter of useState, and modify the first example a bit.
import React, {
useState } from 'react';
function Example() {
// 声明一个叫 "count" 的 state 变量
const [
count, // 在state里面的名字
setCount // 改变这个名字的函数
] = useState(
0 // 初值count的初值
);
return (
<div>
<p>You clicked {
count} times</p>
<button onClick={
() =>
setCount(
count + 1 // 准备把count该成什么样子
)}>
Click me
</button>
</div>
);
}
In the previous class
form, all the variable data was kept in one state
for maintenance, so this state
will become bigger...more and more bloated...more and more difficult to maintain...if there is no comment, it may be difficult to understand...and this is born Redux
.
I personally think that useState
such a pain point can be solved directly. The following is hook
an example I used in a new project .
// 表格loading
const [loading, setLoading] = useState(true);
// 表格数据
const [listData, setListData] = useState({
list: [], total: 0 });
// 当前页码
const [current, setCurrent] = useState(0);
// 搜索数据
const [searchData, setSearchData] = useState({
});
// 医生职称
const [jobTitle, setJobTitle] = useState([]);
// 科室
const [dept, setDept] = useState([]);
// 弹窗显隐
const [visible, setVisible] = useState(false);
// 弹窗数据
const [showData, setShowData] = useState({
});
It can be seen intuitively that basically one piece of data enjoys one useState
piece...with the correct annotations and calling the correct methods, the readability of the code is greatly enhanced.
useEffect
If you are familiar with
React class
the life cycle of a function, you canuseEffect
Hook
be seencomponentDidMount
,componentDidUpdate
andcomponentWillUnmount
these three functions combined.
This sentence comes from the original painting on the official website, and I will explain it to you useEffect
.
useEffect
Will it be executed after every rendering? Yes, by default, it will be executed after the first rendering and after each update.
This is the original words of the official website, it is not difficult to understand, so that you can simulate componentDidUpdate
...you can write the logic you want in the hook and directly upload the official website code.
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>
);
}
You can see that every time you click the button, set了Count
the value is reset , because every update will go to useEffect
(how to not enter every time we will talk about later useEffect
), and useEffect
the logic is that it will be modified every time document.title
.
This simulates that componentDidUpdate
componentDidMount
componentWillUnmount
useEffect
there are actually two parameters, the first is to call the function, and the second is to monitor the value.
useEffect(
() => {
// 我叫A函数
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
This code can be understood as a program runs, it calls a function A, although after each rendering will come to this useEffect
, because he has a second argument, so only [props.source]
change when the function will be called A again.
We can call it flexibly, and this value can be useState
controlled. When you want it to change, you can useState
change its value.
So how can I elegantly make this useEffect
call only once, like componentDidMount
this? You can pass a control value in the second value like this.
useEffect(() => {
const firstGet = async () => {
const [z, x, c] = await Promise.all([
requestZ(),
requestX(),
requestZ(),
]);
// 做你想做的事情
};
firstGet();
}, []);
By analogy, how can i imitate componentWillUnmount
it?
useEffect(() => {
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
}, []);
Why return a function in effect? This is an optional cleanup mechanism for effect. Each effect can return a cleanup function. This way, the logic of adding and removing subscriptions can be put together. They are all part of the effect.
When does React clear the effect? React will perform a cleanup operation when the component is uninstalled. The effect is executed every time it is rendered. This is why React will clear the previous effect before executing the current effect.
These are the original words of the official website. The code in the code return
is to clear. Similarly, put an empty in the second value. This will be cleared very elegantly. The most obvious is that the SMS countdown setInerval, clear
will not keep occupying resources.