Реагировать - ждать, пока данные не будут получены из API - PullRequest
0 голосов
/ 29 января 2020

Я пытаюсь получить некоторые JSON данные, и я использовал async / await, чтобы остановить выполнение, пока загрузка данных не будет готова. Но React, похоже, полностью игнорирует это и пытается визуализировать компонент. Ниже я написал упрощенный код для дальнейшей проверки, и setTimeout имитирует задержку вызова API.

console.log('global');
var index ="Data not loaded";

(async function fetchDataAsync(){
  console.log('async start');

  //mimcs loading data from API calls
  let promise = new Promise((resolve, reject) => {
    setTimeout(() => resolve("Data loaded!"), 1000)
  });

  var index = await promise;
  console.log('async end');
  console.log(index);
})();

class App extends React.Component {
  constructor(props){
    super(props);
    this.state={
      randomIndex:0
    }
    console.log('constructor');
  }
  render(){
    console.log('render');
    return (
      <div > 
        <p>{index}</p>
      </div>
    );
  }
}

Выходные данные показывают Данные не загружены , а консоль показывает ниже

global

asyn c start

конструктор

рендер

asyn c end

Данные загружены!

Так должен работать React или я здесь чего-то не хватает? Что было бы лучшим местом для вызова API, чтобы гарантировать загрузку данных до монтирования компонента. Спасибо

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Это не способ React делать что-либо, ожидая, пока данные поступят перед рендерингом.

Ваш код должен реагировать, и он должен запускать компонент, к которому поступили данные.

Вот как вы можете это сделать

class App extends React.Component {
  constructor(props){
    super(props);
    this.state={
      randomIndex:0,
      data: '',
      loading: false
    }
    console.log('constructor');
  }
  
  fetchDataAsync = async () => {
    console.log('async start');
     this.setState({ loading: true });
    //mimcs loading data from API calls
    let promise = new Promise((resolve, reject) => {
      setTimeout(() => resolve("Data loaded!"), 1000)
    });

    var data = await promise;
    console.log('async end');
    console.log(data);
    this.setState({ loading: false, data });
  }

  render(){
    console.log('render');
    const { loading, data } = this.state;
    if(loading) return (<div className="loader">Loading ... </div>);
    if (!loading && data) {
      return (
        <div > 
          <p>{data}</p>
        </div>
      );
    }
    return null;
  }
}
0 голосов
/ 29 января 2020

Проблема в том, что функция asyn c не задерживает синхронную обработку кода, в котором появляется функция. Под этим я подразумеваю порядок выполнения вашего кода:

  1. Запуск запуск функции async вплоть до await
  2. Создание App класса
  3. ... всего, что у вас есть t показан после класса App; Я предполагаю, что вы используете App где-то ...
  4. Код верхнего уровня завершен
  5. Таймер срабатывает
  6. Обещание, ожидающее таймера, устанавливается
  7. Обещание, созданное вызовом функции asycn, рассчитывается

Обратите внимание, что 2-4 произошло раньше, чем 5-7.

Вместо этого вы захотите сделать либо

  1. Не используйте App, пока у вас нет данных, или

  2. Придайте App состояние ожидания, которое оно отображает в ожидании данных

Каждое из этих решений применимо к различным ситуациям, поэтому вам нужно выбрать то, которое подходит для вашей ситуации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...