https://react.docschina.org/docs/getting-started.html
之前跟大家说过,react文档最重要的是理解这两部分的内容(高级指引部分有时间最好过一遍)。
对于已经掌握过vue知识的人来说,核心概念会较好理解,这篇文章主要是帮助大家理解Hook章节的内容。
从没有hooks说起
在没有hooks之前,react的组件有两种:函数组件,类组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
相比较函数式组件,类组件存在两个函数组件没有的东西
- 状态
生命周期 ```javascript class Clock extends React.Component { constructor(props) { super(props); this.state = {date: new Date()}; }
componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); }
componentWillUnmount() { clearInterval(this.timerID); }
tick() { this.setState({ date: new Date() }); }
render() { return (
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
ReactDOM.render(
查看以上代码,其中 this.state属于状态,它与ui界面息息相关,可以看作Vue中的data,属于数据模型对UI界面的一种映射;其中componentDidMount,componentWillUnmount属于生命周期钩子函数,需要在特定的页面周期才会触发的函数
思考一下一个问题:缺少了状态和生命周期,我们只能做什么样的组件?
答案是:纯组件,或者叫无状态组件,这种组件定义类似于纯函数。
纯函数
> - 它应始终返回相同的值。不管调用该函数多少次,无论今天、明天还是将来某个时候调用它。
> - 自包含(不使用全局变量)。
> - 它不应修改程序的状态或引起副作用(修改全局变量)。
以上来自于网络上对于纯函数的定义,简单来理解就是:输出仅因输入改变,与外部时间等其他因素无关的函数;如 y=f(x), y的值仅根据x改变,与调用时间,调用方式无关。
因此纯组件也就比较好理解了,一个简单的例子就是一个显示文字的组件,它显示的文字由props传入,不管何时何地调用,组件仅与props参数有关。
但是我们可以看到,几乎所有的页面级组件(也叫容器组件)都是需要生命周期和状态的,不然无法应对复杂的业务环境。
因此,在hooks未出现之前,类组件才是react的主流组件。
<a name="lzlry"></a>
### hooks带来了什么
[https://react.html.cn/docs/hooks-intro.html](https://react.html.cn/docs/hooks-intro.html)<br />[https://react.html.cn/docs/hooks-overview.html](https://react.html.cn/docs/hooks-overview.html)
以上两个链接属于官方解释什么是hooks以及为什么要引入hooks,这里不再赘述,我仅仅只介绍两个最常用的hooks:useState,useEffect,并且从中分析hooks带来的好处。
```javascript
import { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 这里类比 this.state = { count: 0 }
// this.setState({ count: xxx})
useEffect(() => {
document.title = `You clicked ${count} times`;
});
// 默认情况下,效果在每次完成渲染后运行,一种副作用hooks
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
可以看到,useState比较好理解,相当于为函数组件引入了状态,不过需要注意
const [count, setCount] = useState(0);
// useState(0) 代表初始值为0,返回count为 state 变量,
// setCount为修改函数,必须要要用这个函数进行修改,不然无法触发ui更新
useEffect, effect在英文中的意思是副作用,那么什么是副作用呢?
还记得之前提到的纯组件吗?纯组件中,所有的逻辑应该是与时间状态无关的,但是很显然,为了实现类似于生命周期的效果,我们不得不违背这个原则,useEffect则是在这个背景下应运而生的函数。
useEffect(() => {}); 仅传入一个函数,则默认组件每次渲染都会运行一次
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// Clean up the subscription
subscription.unsubscribe();
};
});
// 在函数中return一个函数,意味着在组件卸载时会运行这个函数,类似于componentWillUnMount
useEffect(
() => {
const subscription = source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[source],
);
// 传入第二个参数source,意味着source每次变化都会导致第一个参数中的函数重新运行一次
useEffect(() => {
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
}, []);
// 传入第二个参数为一个空数组,意味着此函数只会运行一次,return的函数则在卸载时运行一次,
// 类似于componentDidMount 和 componentWillUnmount
可以发现,利用useEffect可以实现比生命周期函数更灵活的功能,如,依赖于某个或多个变量变化而触发的effect,对于同一个副作用不用分割在不同的生命周期函数。
更多
hooks除了useState,useEffect之外,还有很多其他api,官方文档如下:
https://react.html.cn/docs/hooks-reference.html
如何练习
参考:https://www.yuque.com/ironknt/ptxgfr/sv5zmt
运行一个ant design pro demo,里面的页面都是依赖于hook的函数组件,可以尝试阅读,修改,模仿来更好的学习hook的使用