Как правильно использовать асинхронные методы в качестве реквизита в ReactJ?У меня есть приложение, которое монтирует «приборную панель» компонента, и этот компонент затем загружает два выпадающих меню.Первый выпадающий список заполняется async 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
});
}
}