React - 在渲染之前等待承诺

React - wait for promise before render

我想不通,如果你能给我指出正确的方向。在我的 NavMenu.js 上,我有登录(两个输入和一个提交按钮,我在上面调用 handleSubmit()

handleSubmit() 中,我正在检查用户登录凭据,效果很好,但在我确认登录后,我继续执行下一次提取以检查用户角色(和 returning 承诺)和可见性在申请中

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')

from helper,它发送this.state.loggedUserRoles作为参数,它应该被填充到fetch from handleSubmit()但是它是未定义的,fetch finish,设置loading on 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 函数调用,而且我还可以看到应用程序继续渲染并且不等待 [=51] 的承诺=] 填充 loggedUserRoles.

的状态

所以问题是,为什么渲染不等待我的角色获取,也不等待 promise 解决后再将加载设置为 true?

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

据我所见和理解,你正在打电话

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

如果反应没问题。这将导致来自 React 的异步调用,以便在有时间时设置新状态。

但是你需要来自

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

每当您想将 userLogged 设置为 true 时,对吗?

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

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

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

编辑:

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

var result = Promise.resolve(roleData)

return result;

这将直接导致空数组,因为这是 roleData 的初始值。因此,您总是从该方法返回一个空数组,而不必担心获取的结果。

您有多种方法可以解决这个问题。我更喜欢使用 async/await:

的简洁易读的方式
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;

或者如果您想继续使用 Promise:

function getAllRoles(formName, sessionVarName){
  return new Promise((resolve, reject) => {
    var roleId = sessionStorage.getItem('UserLoggedRoleId');

    fetch(...)
    .then(roleResponse => roleResponse.json())
    .then(data => {
      sessionStorage.setItem(sessionVarName, JSON.stringify(data));
      resolve(data);
    });