reactjs - 如何在 Reactjs 16.7.0 中使用异步服务器调用
问题描述
在 ReactJs 中使用异步方法作为道具的正确方法是什么?我有一个安装组件“仪表板”的应用程序,然后该组件加载两个下拉菜单。第一个下拉列表由生命周期方法fetch
中的异步填充。componentDidMount
当第一个下拉列表更改时,将触发异步事件处理程序并且selectedAId
应该设置 state 属性。如果我在浏览器中调试它,我会看到这个状态道具集。设置状态后,相同的事件处理程序还调用异步服务器方法以基于 state 属性获取一些数据selectedAId
。
如果我然后转到异步服务器方法getEntitledSites
,则发送给该方法的参数是“0”,而不是我之前看到的在事件处理程序中设置的值。
以下是代码摘要的要点:
https://gist.github.com/thehme/c4b5a958ef1a6e5248f697375c9cb84b#file-api-ts-L15
api.ts
class Api {
...
async getEntitledForA() {
try {
const orgsResponse = await fetch('/api/v1/orgs');
const orgResponseJson = await orgsResponse.json();
return orgResponseJson.data;
} catch (err) {
console.error(err);
return null;
}
}
async getEntitledSites(orgId: number) {
try {
const sitesResponse = await fetch('/api/v1/study/' + orgId + '/sites');
const sitesResponseJson = await sitesResponse.json();
return sitesResponseJson;
} catch (err) {
console.error(err);
return null;
}
}
}
export default new Api();
仪表板.jsx
import React, {Component} from 'react';
import SelectDropDownA from '../components/SelectDropDownA';
import SelectDropDownB from '../components/SelectDropDownB';
import SelectDropDownC from '../components/SelectDropDownC';
class CreateDashboard extends Component {
constructor() {
super();
this.state = {
organizations: [],
sites: [],
selectedAId: "0",
selectedBId: "0",
selectedCId: "0",
showBMenu: false
}
}
async componentDidMount() {
let organizations = await Api.getEntitledForA();
this.setState({ organizations });
}
async onSelectedOrgChange(selectedOrgId) {
if (selectedOrgId !== 0) {
this.setState({ selectedAId });
let sitesData = await Api.getEntitledSites(this.state.selectedAId);
this.setState({
sites: sitesData.sites,
showSitesMenu: true
});
}
}
...
render() {
return (
<div className="panel">
<div className="insidePanel">
<SelectStudyDropDown
onChange={e => this.onSelectedOrgChange(e.target.value)}
...
/>
</div>
{this.showSitesMenu &&
<div className="insidePanel">
<SelectSiteDropDown
onChange={e => this.onSelectedSiteChange(e.target.value)}
...
/>
</div>
}
</div>
)
}
}
export default CreateDashboard;
我想知道这是否与我的使用方式async/await
或方法的绑定有关onChange
。
解决方案:在我的特殊情况下,我不需要在启动服务器请求之前this.state
进行设置selectedAId
,因此通过将参数直接传递给请求,可以正常工作。然后我可以简单地将 的设置移动selectedAId
到this.setState
. 如果我需要selectedAId
在发出服务器请求之前进行设置,这是行不通的,在这种情况下,我必须等待this.state
完成设置,但事实并非如此,因为我希望我的服务器请求立即开始。
async onSelectedOrgChange(selectedOrgId) {
if (selectedOrgId !== 0) {
let sitesData = await Api.getEntitledSites(selectedOrgId);
this.setState({
selectedAId,
sites: sitesData.sites,
showSitesMenu: true
});
}
}
解决方案
this.setState
是异步且不可等待的(即不返回承诺),因此如果您想在设置新状态后对其执行某些操作,则需要在回调中执行此操作:
this.setState({ selectedAId }, async () => {
let sitesData = await Api.getEntitledSites(this.state.selectedAId);
this.setState({
sites: sitesData.sites,
showSitesMenu: true
});
});
此外,在您的示例中,onSelectedOrgChange
未绑定到this
任何地方。但是,如果这是一个问题,那么整个事情很久以前就会坏掉,所以我想你只是不小心把它漏掉了?
此外,我建议您提取e.target.value
处理程序内部并作为道具传递onChange={this.onSelectedOrgChange}
,因为在您当前的代码中,onChange
每次调用 render 时都会创建一个新的处理程序。
推荐阅读
- python - 我不能使用标签传递变量
- javascript - 在 ReactJS 中为可能的算术运算获取表单输入法的值
- azure-data-explorer - 用于分组 AppInsights 消息的 Kusto 查询
- javascript - 我想按类将 H2 - H5 标签替换为 P
- python - 使用 Python 在 SQL Server 2019 上创建随机用户
- flutter - 如何在颤振上创建带有圆角的方形头像?
- python - 全局关闭 Colorama 颜色代码
- linux - Xrandr 检测到但不连接 HDMI
- reactjs - 片段不在本地主机中呈现(第一个反应应用程序)
- php - 如何在php中解析xml子树