reactjs - React 组件生命周期和启动异步流程
问题描述
考虑一个 ReactJS 场景,一个有状态的组件负责从外部 HTTP API 获取信息并呈现它。它还负责重新获取该信息以响应 DOM 事件(例如按钮单击)或时间间隔。
如果我正确理解了新的 ReactJS 16.3 生命周期:
componentDidMount
是开始初始提取的正确位置。componentWillUnmount
应该用于取消任何挂起的提取。
但是,我有一个关于响应异步事件的额外提取的问题,例如按钮单击处理程序或setInterval
处理程序:
事件处理程序是否应该使用
setState
(例如setState({loading:true})
)安排新状态,并且甚至在新状态提交之前也开始 HTTP 获取?或者,只在处理程序中安排新状态,并且只在新状态提交给 DOM 之后
setState
才在 中启动 HTTP 获取。componentDidUpdate
类似的情况是如果由于组件props
更改而需要新的提取。在这种情况下,我假设componentDidUpdate
始终是开始新获取的正确位置,即因为getDerivedStateFromProps
或shouldComponentUpdate
发生在渲染阶段。
谢谢,佩德罗
解决方案
相信大家看一些示例代码会比较容易。如果我不使用 Redux,我会这样做:
import React, { Component } from "react";
class ItemView extends Component {
state = {
fetching: false
};
componentDidMount() {
this.fetchItems();
// Fetch items every 10 seconds
this.interval = setInterval(() => {
this.fetchItems();
}, 10 * 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
if (this.state.fetching) {
this.isUnmounted = true;
}
}
fetchItems = () => {
this.setState({
fetching: true
});
return fetch("https://api.example.org/items").then(response => {
if (!this.isUnmounted) {
this.setState({
fetching: false,
items: response.json().items
})
}
}).catch(e => {
if (!this.isUnmounted) {
this.setState({
fetching: false,
error: e.message
});
}
})
};
}
现在,回答您的问题:
getDerivedStateFromProps
是一个同步操作,在初始渲染后和收到新道具后触发。因此,我不建议将异步操作放在这里。它也是渲染阶段的一部分(检查第二点)。React 生命周期有两个阶段:The
render
和commit
Phase。React 会比较阶段中要完成的更改,render
并且此阶段的生命周期可以在发生之前多次触发commit
。对 DOM 的更改是在commit
阶段中进行的。ComponentDidUpdate
在阶段之后调用commit
,因此我建议它是执行异步操作的正确位置,以便您可以显示加载状态,直到您收到来自 API 的响应并且您不会多次触发请求。最后但同样重要的是,我会使用 Redux 并将 fetch 逻辑移到组件之外,这样我们就不必处理竞争条件(例如,组件之类的情况已经卸载,直到我们收到来自 api 或父组件的响应同时更新道具)。
如果您不想使用该isUnmounted
模式(请在此处查看原因),您可以考虑使用可取消的承诺。
推荐阅读
- ios - 撤销当前的 APNs 密钥会破坏实时应用程序吗?
- java - 将 REST 查询参数存储为静态字段
- collision - 与触发器碰撞玩家并让玩家返回主菜单的问题
- coldfusion - CFCHART 整体显示 y 轴数字
- angular - 将 p-table 列的当前页面中的数据传递给另一个应用程序
- postgresql - 如何根据传递给 SQL 函数的 ID 返回不同的表数据
- javascript - JavaScript:利用 setInterval() 调用类方法
- php - 其他元素未返回正确结果
- python - 向多个 csv 文件添加标题
- powershell - 在 PS 中动态设置属性