如何在Reactjs 16.7.0异步调用服务器工作

问题描述 投票:-1回答:1

什么是使用异步方法作为ReactJs道具的正确方法是什么?我有安装组件“仪表板”,然后这个组件加载两个下拉菜单的应用程序。第一下拉由异步fetchcomponentDidMount生命周期方法填充。

当第一个下拉的变化,异步触发事件处理程序和国家财产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/awaitonChange方法的结合做。

解决方案:在我的具体情况,我不需要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
        });
    }
}
reactjs async-await
1个回答
0
投票

this.setState是异步的,而不是awaitable(即不返回的承诺),所以如果你想用它做什么的设置后,新的状态,你需要做的是在回调中:

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处理程序,每次渲染被调用。

© www.soinside.com 2019 - 2024. All rights reserved.