Получить данные в ReactJS

В componentDidMount() есть запрос на получение

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result)
      console.info(manufacturers)
    });
  });

  this.setState({
    participants: manufacturers
  })
}

Этот console.info(manufacturers) показывает, что в массиве есть объекты, но состояние компонента пустое. Как правильно установить его после получения данных?

Код функции Get():

const Config = require('Config')
export async function Get(type, userData) {
    let BaseURL = Config.serverUrl;
    let result = {};
    if (userData)
        result = await fetch(BaseURL+type, {
                method: 'GET',
                headers: new Headers({
                    'Authorization': 'Bearer ' + userData,
                    'Content-Type': 'application/json'
                })
        });
    else
        result = await fetch(BaseURL+type, {
            method: 'GET',
            headers: new Headers({
                'Content-Type': 'application/json'
            })
        });
    let data = await result.json();
    return data;
}
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
154
6

Ответы 6

Вам нужно установитьState в обратном вызове Get обещания

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result)
      console.info(manufacturers)
      this.setState({
        participants: manufacturers
      })
    });
  });
}

Вам следует переместить this.setState внутрь .then. Точно не знаю, почему вы сначала отправляете данные в массив производителей. Если вы используете этот массив для чего-то. Если у вас уже есть результат в состоянии, вам, вероятно, не понадобится массив производителей. Если нет ... Вы можете просто установить состояние с результатом, как показано ниже:

componentDidMount() {
   var manufacturers = []

   this.props.participants.map(participant => {
     Get("manufacturer/" + participant.id, "").then(result => {
      manufacturers.push(result) // Do you need this?
      console.info(manufacturers)
        this.setState({
          participants: result
        })
    });
  });
}

Проблема связана с асинхронной логикой. Использование this.setState() вне then() выборки приводит к тому, что свойство manufacturers становится пустым.

В вашем случае сложность заключается в том, что вам необходимо разрешить несколько запросов параллельно перед обновлением состояния. Это можно сделать с помощью функции Promise.all():

componentDidMount() {
  Promise.all(this.props.participants.map(participant =>
    Get("manufacturer/" + participant.id, "")
  ).then(results => {
    this.setState({
      participants: results // or results.map(result => result.data()) ...
    })
 })
}

Инициализируйте состояние перед вызовом метода ComponentDidMount:

constructor() {
    super();
    this.state = { participants:null }
}

Поскольку у вас есть несколько вызовов Get, и каждый из них - async, вам придется подождать, пока весь результат не будет collected, а затем установить его в состояние. Вы можете сделать это, используя Promise.all, который может сначала разрешить все вызовы wait, а затем установить данные в состояние.

Сначала я бы создал функцию Get и вызвал ее в async.

componentDidMount() {
  this.fetchAllData();
}

Затем внутри этого метода дождитесь разрешения всех componentDidMount и установите его в состояние, когда у нас есть данные. вам, возможно, придется обернуть всю функцию внутри блока Promises, чтобы, если есть какое-либо отклонение обещания из-за сбоя сетевого вызова, вы могли обработать его соответствующим образом.

fetchAllData = async () => {
  const manufacturers = await Promise.all(
    this.props.participants.map(participant => 
      Get("manufacturer/" + participant.id, ""))
  )
  this.setState(manufacturers)
};

вы всегда должны обновлять State в 'then' или поймать блок обещания, когда обещание разрешено / отклонено ... как показано ниже

componentDidMount() {
var manufacturers = []

this.props.participants.map(participant => {
 Get("manufacturer/" + participant.id, "").then(result => {
  manufacturers.push(result);

   this.setState({participants: manufacturers});
   console.info(manufacturers);

  });
 });
}

Поскольку ваша функция get возвращает обещание, которое является асинхронным вызовом, при выполнении функции get она переходит к следующей строке кода, прежде чем разрешить this.setState () в вашем случае, следовательно, не отображается обновленное состояние. Всегда помните, что setState () сам по себе является асинхронным, и если вам нужно выполнить какую-либо операцию после setState, сделайте это в необязательном аргументе обратного вызова setState (), например: -

this.setState((currentState)=>{
 // you can access the currentState here
 },()=>{
 //your callback... here you can access directly this.state since it is guranteed 
  //that it will be updated state always
});

Другие вопросы по теме