React 组件生命周期
组件是任何 React 应用程序的构建块,而一个 React 应用程序由多个组件组成。生命周期方法用于在组件生命周期的不同阶段与组件进行交互。
一般来说,React 组件的生命周期可以分为三类:
- 安装
- 更新
- 卸载
我们先把上述类别中各个生命周期方法的调用顺序列出来,然后再详细讲解各个方法的细节。
安装:
在组件初始化期间,当创建组件实例并将其插入到 DOM 中时,将按照列出的顺序调用以下方法:
- 构造函数()
- 静态 getDerivedStateFromProps()
- 使成为()
- 组件挂载()
更新中:
当组件由于 props 或 state 等改变而重新渲染时,将调用以下方法:
- 静态 getDerivedStateFromProps()
- 应该组件更新()
- 使成为()
- 获取更新前的快照()
- 组件更新()
卸载:
从 DOM 中卸载或移除组件时,仅调用一个 React 生命周期方法:
- 组件将卸载()
生命周期方法解释:
现在让我们详细讨论 React 组件生命周期方法。
使成为():
React 组件最重要的生命周期方法,也是唯一必须的方法。它应该是纯方法,这意味着它不会修改组件状态,每次调用都返回相同的结果,并且不直接与浏览器交互。
它返回一个表示渲染过程中组件的元素,该元素可以是原生 DOM 组件(例如<p/>
)或其他用户定义组件的表示。如果不需要渲染任何内容,则返回 null 或 undefined。
组件的道具或状态发生任何变化后,都会调用此功能。
render() {
return (
<div>
Hello World!
</div>
);
}
如前所述,它不应该修改组件状态,这意味着 setState() 不能在 中定义render()
。如果你尝试这样做,setState()
它会不断地调用 render ,这将导致无限循环,最终导致应用程序崩溃。
组件挂载():
组件挂载后立即调用,这意味着所有元素均已正确渲染。此方法可用于:
- 获取数据
- 添加事件监听器
- 操作 DOM 元素
- 设置订阅
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = { data: 'Michael Jordan' }
}
loadPageData (){
setTimeout(() => {
console.log('Our data is fetched');
this.setState({ data: 'Hello…' })
}, 1000)
}
componentDidMount(){
this.loadPageData();
}
render() {
return( <div> {this.state.data} </div> )
}
}
export default App;
在上面的例子中,我们在组件挂载后加载页面数据。在componnetDidMount()
生命周期方法中,我们loadPageData()
调用了用于模拟网络请求的方法setTimeout()
。获取数据后,我们用它setState()
来改变组件的状态并使其渲染。
获取派生状态(从Props获取):
此方法仅适用于状态依赖于 props 变化的罕见用例。它会在调用该render()
方法之前立即调用,无论是在初始挂载时还是后续更新时。它应该返回一个对象来更新状态,或者返回 null 来不更新任何内容。
应该更新组件():
仅当收到新的 props 或 state 时,此方法才会在 render 生命周期方法之前调用。它返回 true 或 false。默认情况下,返回值始终为 true。
forceUpdate()
它只是为了性能优化而添加为生命周期方法。在初始渲染期间或调用时不会调用此方法。
获取快照更新前()
它会在 render() 方法对 DOM 所做的最新更改生效之前调用。例如,如果我们向列表中添加了多个项目,并且在它们渲染之前,我们想要获取前一个列表项的最后一个项目的滚动位置,则可以使用此方法来获取该位置。
此方法不常用。从此方法返回的任何值都将作为参数传递给 componentDidUpdate() 生命周期方法。
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// Snapshot value is only passed when there are new items.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}></div>
);
}
}
组件更新():
此方法是 的更新版本ComponentDidMount()
。除了组件第一次渲染时,每次组件更新后都会调用该方法。
componentDidUpdate()
接受两个参数,prevProps
和prevState
。如果组件还实现了getSnapshotBeforeUpdate()
,则第三个参数“snapshot”也会作为参数传递给此方法。
componentDidUpdate(prevProps, prevState, snapshot) {
if (this.props.Id !== prevProps.Id) {
this.reloadData();
}
}
组件将卸载():
此方法在组件即将被销毁之前调用。在这个生命周期方法中,我们执行所有清理工作,例如终止网络请求、取消订阅、重置计时器等。
setState()
不应在此方法中调用,我们将销毁我们的组件。
import React, { Component } from 'react';
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
incrementTime() {
this.setState({
date: new Date()
});
}
componentDidMount() {
this.timerInterval = setInterval(() => {
this. incrementTime ();
}, 1000);
}
componentWillUnmount() {
clearInterval(this. timerInterval);
}
render() {
return (
<div>It is {this.state.date.toLocaleTimeString()}.</div>
);
}
}
在这个例子中,我们可以看到我们已经在页面上渲染了时间间隔,并使用 来增加它。现在,当组件即将销毁时,我们将在生命周期方法setInterval()
中清除此间隔。componentWillUnmount()
希望本文对您有所帮助。如果您有任何疑问,或者觉得我遗漏了什么,欢迎留言。
如果您喜欢这篇文章,请点赞或留言。
您可以在Twitter上关注我,或者在我的个人网站jaycaetano.com上查找我的其他作品。
文章来源:https://dev.to/jaylcaetano/react-component-lifecycle-2npl