反应-在渲染之前等待承诺

时间:2019-01-12 20:12:51

标签: reactjs async-await render

如果您能指出正确的方向,我将无法解决。在NavMenu.js上,我具有LogIn(两个输入和一个提交按钮,在该按钮上,我叫handleSubmit()

handleSubmit()中,我正在检查用户登录凭据是否有效,但是在确认登录后,我继续进行下一次访存以检查用户角色(并返回承诺)和在应用程序中的可见性

Helper.js

function getAllRoles(formName, sessionVarName) {

    var roleData = [];
    var roleId = sessionStorage.getItem('UserLoggedRoleId');

    fetch('api/User/GetUserRole/', {
    'method': 'POST',
    headers: {
        'Accept': 'application/json, text/plain, */*',
        'Content-Type': 'application/json'
    },
    'body':
        JSON.stringify({
            'roleId': roleId,
            'formName': formName
        })
    }).then(roleResponse => roleResponse.json())
    .then(data => {
        sessionStorage.setItem(sessionVarName, JSON.stringify(data));
        roleData = data;
    });

  var result = Promise.resolve(roleData)

  return result;
}

function checkRoleVisibility(userRoles, role) {} <-- return true or false

export {
  getAllRoles ,
  checkRoleVisibility   
};

在NavMenu.js中

import { getAllRoles, checkRoleVisibility } from './common/Helper';

handleSubmit() {

 fetch('api/User/UserAuthentification/', 
 ....then(response => {
       if (response.ok) {
               this.setState(prevState => ({ userLogged: !prevState.userLogged }))

               response.json().then(value => {

               sessionStorage.setItem('UserLogged', true);
               sessionStorage.setItem('UserLabelSession', this.state.userLabel);
               sessionStorage.setItem('UserLoggedRoleId', value.userRole.roleID);

               getAllRoles('NavMenu', 'UserLoggedRoles')
                     .then(roleData => {
                            this.setState({
                                loggedUserRoles: roleData,
                                loading: false
                            });
                        });

               this.props.alert.success("Dobro dosli");
        })
   }
}

但是问题来了,就是在render()本身中,我有一个控件navBar调用

checkRoleVisibility(this.state.loggedUserRoles, 'SeeTabRadniNalozi')
来自帮助程序的

,该函数发送this.state.loggedUserRoles作为参数,该参数假定是从handleSubmit()进行获取,但未定义,获取完成,将loading设置为true,渲染完成,但没有什么都不显示

我有this.state.loading,并据此显示控制权...

    let navMenu = this.state.loading ? <div className="loaderPosition">
        <Loader type="Watch" color="#1082F3" height="200" width="200" />
    </div> : !this.state.userLogged ? logInControl : navBar;

如果我在控制器上设置了一个断点,我可以看到我的方法正在被getAllRoles函数调用,但是我也可以看到该应用程序继续进行渲染,并且不等待承诺返回到的填充状态loggedUserRoles

问题是,为什么在将load设置为true之前,渲染既不等待我的角色获取,也不等待promise解析呢?

我检查了这个答案Wait for react-promise to resolve before render,然后将this.setState({ loading: false });放在了componentDidMount()上,但是加载的div显示为全时显示

1 个答案:

答案 0 :(得分:1)

据我了解,你在打电话

this.setState(prevState => ({ userLogged: !prevState.userLogged }))

如果响应正常。这将导致React进行异步调用,以便在有时间时设置新的状态。

但是您需要来自

的资源
this.setState({
  loggedUserRoles: roleData,
  loading: false
});

何时要将userLogged设置为true,对吗?

因此,可能是在您将loggedUserRoles设置为true之前,React调用已渲染。如果我对您的理解正确,那将会导致错误。

您可以像这样简单地将userLogged状态设置为其他状态:

userLogged

编辑:

此外,您想在getAllRoles中更改Promise创建。你要回来

this.setState({
  userLogged: true,
  loggedUserRoles: roleData,
  loading: false
});

这将直接导致空数组,因为这是var result = Promise.resolve(roleData) return result; 的初始值。因此,您总是从该方法返回一个空数组,而不必理会所获取的结果。

您有多种解决方法。我更喜欢使用async / await的简洁易读的方式:

roleData

或者如果您想留下来承诺

async getAllRoles(formName, sessionVarName){
  var roleId = sessionStorage.getItem('UserLoggedRoleId');

  const response = await fetch(...);
  const data = response.json();

  sessionStorage.setItem(sessionVarName, JSON.stringify(data));
  return data;