Реагировать - дождаться обещания, прежде чем сделать - PullRequest
0 голосов
/ 12 января 2019

Я не могу понять это, если вы можете указать мне правильное направление. На моем NavMenu.js у меня есть логин (два входа и кнопка отправки, на которую я звоню 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   
};

In 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.

Итак, вопрос в том, почему рендеринг не ждет получения моей роли и не ждет обещания разрешить, прежде чем установить загрузку на true?

Я проверил этот ответ Подождите, пока ответное обещание разрешится, прежде чем визуализировать , и я поставил this.setState({ loading: false }); на componentDidMount(), но затем загрузка div показывается полный рабочий день

1 Ответ

0 голосов
/ 12 января 2019

Из того, что я вижу и понимаю, вы звоните

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
});

EDIT:

Кроме того, вы хотите изменить свое создание Promise внутри getAllRoles. Вы возвращаетесь

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);
    });
...