在ReactJs中使用异步方法作为道具的正确方法是什么?我有一个安装了组件“仪表板”的应用程序,然后该组件加载了两个下拉菜单。第一个下拉列表由fetch
生命周期方法中的异步componentDidMount
填充。
当第一个下拉列表更改时,将触发异步事件处理程序,并应设置状态属性selectedAId
。如果我在浏览器中调试它,我会看到此状态属性集。设置状态后,同一事件处理程序还会调用一个异步服务器方法来根据状态属性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();
dashboard.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
});
}
}
答案 0 :(得分:0)
this.setState
是异步的并且不等待(即不返回promise),因此,如果要在设置新状态后对新状态进行操作,则需要在回调中完成该操作:>
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
处理程序被称为。