30天入坑React ---------------day07 Lifecycle Hooks
这篇文章是30天React系列的一部分 。
在本系列中,我们将从非常基础开始,逐步了解您需要了解的所有内容,以便开始使用React。如果您曾经想学习React,那么这里就是您的最佳选择!
下载免费的PDF
生命周期钩子
在Github上编辑此页面
今天,我们将介绍一些我们可以与React组件一起使用的最常见的生命周期钩子,我们将讨论它们为什么有用以及何时应该使用它们。
恭喜!我们已经在React的第一周结束了,我们已经覆盖了很多。我们刚刚完成了有状态组件的工作,以跟踪组件的内部状态。今天,我们将暂停实现,并谈谈组件如何存在于应用程序中。也就是说,我们将讨论组件的生命周期。
当React安装我们的应用程序时,它为我们提供了一些钩子,我们可以在组件的生命周期中的不同时间插入我们自己的功能。为了挂钩生命周期,我们需要在我们的组件上定义函数,React在适当的时候调用每个钩子。让我们深入了解第一个生命周期钩子:
componentWillMount()
/ componentDidMount()
当在我们的应用程序的页面上定义组件时,我们不能立即依赖它在DOM中可用,因为我们正在定义虚拟节点。相反,我们必须等到组件本身实际安装在浏览器中。对于我们在安装时需要运行的功能,我们可以获得两个不同的钩子(或函数)。在组件之前调用的一个是在页面上安装的,另一个是在组件安装之后调用的。
什么
mounting
意思?由于我们使用React在DOM树中定义节点的虚拟表示,我们实际上并没有定义DOM节点。相反,我们正在建立React为我们维护和管理的内存视图。当我们谈论安装时,我们讨论的是将虚拟组件转换为React放置在DOM中的实际DOM元素的过程。
这对于诸如获取数据以填充组件之类的内容非常有用。例如,假设我们想要使用我们的活动跟踪器来显示github事件。我们只想在要呈现数据本身时加载这些事件。
回想一下,我们Content
在活动列表中定义了我们的组件:
class Content extends React.Component {render() {
const {activities} = this.props; // ES6 destructuring
return (
<div className="content">
<div className="line"></div>
{/* Timeline item */}
{activities.map((activity) => (
<ActivityItem
activity={activity} />
))}
</div>
)
}
}
让我们更新Content
组件以向github.com事件api发出请求,并使用响应来显示活动。因此,我们需要更新state
对象。
正如我们昨天所做的那样,让我们 通过设置this.state
构造函数中的对象来更新我们的组件是有状态的
class Content extends React.Component { constructor(props) {
super(props);
this.state = {
activities: []
}
}
// ...
}
现在,我们将要在组件本身准备好安装时(或者在安装之后)发出HTTP请求。通过在我们的组件中定义函数componentWillMount()
(或componentDidMount()
),React在它安装到DOM之前运行该方法。这是我们添加GET
请求的最佳位置。
让我们Content
用github api的请求更新组件。由于我们只想显示一个小列表,让我们来看看最新的四个事件。
我们已经存储了一个github数据的静态JSON文件,我们将直接从源码加载(我们将在几天后回到发出AJAX请求)使用promises。现在,让我们关注如何使用新数据实现更新组件:
class Content extends React.Component { // ...
componentWillMount() {
this.setState({activities: data});
}
// ...
}
请注意,我们没有更改Content
组件中的任何其他内容,它只是起作用。
componentWillUpdate()
/ componentDidUpdate()
有时我们会在更改实际渲染之前或之后更新组件的某些数据。例如,假设我们想调用一个函数来设置渲染,或者在组件的props改变时调用一个函数集。该componentWillUpdate()
方法是一个合理的钩子来处理准备我们的组件进行更改(只要我们不调用this.setState()
它来处理它,因为它会导致无限循环)。
由于我们不需要深入处理这个问题,我们不会担心在这里建立一个例子,但知道它存在是很好的。我们将使用的一个更常见的生命周期钩子是componentWillReceiveProps()
钩子。
componentWillReceiveProps()
当组件即将接收新的时,React将调用方法props
。这是第一个在组件要接收一组新道具时调用的方法。定义此方法是查找特定更新的好时机,props
因为它使我们有机会计算更改并更新组件的内部状态。
这是我们可以根据新道具更新状态的时间。
这里要记住的一件事是,即使
componentWillReceiveProps()
调用该方法,它的值props
也可能没有改变。它总是以检查道具值的变化是一个好主意。
例如,让我们在活动列表中添加一个刷新按钮,这样我们的用户就可以请求重新请求github事件api。
我们将使用componentWillReceiveProps()
钩子来请求组件重新加载它的数据。由于我们的组件是有状态的,我们将希望用新数据刷新此状态,因此我们不能简单地更新props
组件。我们可以使用该componentWillReceiveProps()
方法告诉我们想要刷新的组件。
让我们在包含元素上添加一个按钮,该按钮传递一个requestRefresh
布尔值,告诉Content
组件刷新。
class Container extends React.Component { constructor(props) {
super(props);
this.state = {refreshing: false}
}
// Bound to the refresh button
refresh() {
this.setState({refreshing: true})
}
// Callback from the `Content` component
onComponentRefresh() {
this.setState({refreshing: false});
}
render() {
const {refreshing} = this.state;
return (
<div className='notificationsFrame'>
<div className='panel'>
<Header title="Github activity" />
{/* refreshing is the component's state */}
<Content
onComponentRefresh={this.onComponentRefresh.bind(this)}
requestRefresh={refreshing}
fetchData={fetchEvents} />
{/* A container for styling */}
<Footer>
<button onClick={this.refresh.bind(this)}>
<i className="fa fa-refresh" />
Refresh
</button>
</Footer>
</div>
</div>
)
}
}
<Footer />
请注意,我们在这里有一个新元素,用于显示元素的子元素。这是一种允许我们在某些内容周围添加CSS类的模式。
class Footer extends React.Component {
render() {
return (
<div className='footer'>
{this.props.children}
</div>
)
}
}
使用这个新的prop
(requestRefresh
prop),我们可以在更改值时更新activities
我们的state
对象。
class Content extends React.Component { // ...
componentWillReceiveProps(nextProps) {
// Check to see if the requestRefresh prop has changed
if (nextProps.requestRefresh !== this.props.requestRefresh) {
this.setState({loading: true}, this.updateData);
}
}
// ...
}
时间
此演示使用来自JSON文件的静态数据,并在刷新时随机选取四个元素。这是为了模拟刷新而设置的。
componentWillUnmount()
在卸载组件之前,React将调用componentWillUnmount()
回调。这是处理我们可能需要的任何清理事件的时间,例如清除超时,清除数据,断开websockets等。
例如,我们上次使用的时钟组件,我们设置每秒调用一次超时。当组件准备好卸载时,我们希望确保清除此超时,以便我们的JavaScript不会继续为实际不存在的组件运行超时。
回想一下,timer
我们构建的组件如下所示:
class Clock extends React.Component { constructor(props) {
super(props);
this.state = this.getTime();
}
componentDidMount() {
this.setTimer();
}
setTimer() {
this.timeout = setTimeout(this.updateClock.bind(this), 1000);
}
updateClock() {
this.setState(this.getTime, this.setTimer);
}
getTime() {
const currentTime = new Date();
return {
hours: currentTime.getHours(),
minutes: currentTime.getMinutes(),
seconds: currentTime.getSeconds(),
ampm: currentTime.getHours() >= 12 ? 'pm' : 'am'
}
}
// ...
render() {
}
}
当我们的时钟将被卸载时,我们将要清除我们在setTimer()
组件上的函数中创建的超时。添加该componentWillUnmount()
功能可以完成这种必要的清理工作。
class Clock extends React.Component { // ...
componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
}
// ...
}
12 :52:01 日下午
这些是我们可以在React框架中与之交互的一些生命周期钩子。在构建我们的反应应用程序时,我们会使用这些,因此熟悉它们,它们存在以及如何挂钩组件的生命是一个好主意。
我们确实在这篇文章中引入了一个新概念,我们在其中添加了一个回调函数:我们在一个要从子进程调用的组件上添加了一个回调函数。在下一节中,我们将讨论如何定义和记录prop
组件的API,以便在跨团队和应用程序共享组件时使用。
学习REACT正确的方法
React和朋友的最新,深入,完整的指南。
下载第一章
❮上一个
下一章:
包装和PropTypes
下一个 ❯
本教程系列的完整源代码可以在GitHub repo上找到,其中包括所有样式和代码示例。
如果您在任何时候感到困难,还有其他问题,请随时通过以下方式与我们联系:
- 在文章末尾评论这篇文章
- 通过[email protected]发送电子邮件给我们
- 加入我们的gitter室
- 发送电子邮件至@fullstackreact
以上是 30天入坑React ---------------day07 Lifecycle Hooks 的全部内容, 来源链接: utcz.com/z/382867.html