Проблема с promise'ами в ReactJS

286
07 июля 2017, 08:16

Здравствуйте, вот в чем заключается проблема: когда я через API беру данные с сайта с помощью axios, подключаю этот файл к компоненту, в компоненте записываю результат функции запроса к API в новую переменную в state, то туда записывается pending Promise, а через секунду promise обновляется и получает в [[PromiseValue]] объект с данными, так вот как записать этот объект в переменную из state, а не пустой promise?

Код прилагается:

var axios = require('axios');
export default function getWeatherData( town ) {
  const SITE_URL = "http://api.openweathermap.org/data/2.5/weather";
  const PRIVATE_ID = "8fd3926fd8c6c";
  let request = `${SITE_URL}?q=${town}&APPID=${PRIVATE_ID}`;
  return axios.get(request)
    .then(r => r.data);
}

А также код компонента:

import React, { Component } from 'react';
import './App.css';
import getWeatherData from './api/getWeather';
class App extends Component {
  state = {
    weatherData: getWeatherData('Kiev')
  } 

  componentDidMount() {
    console.log(this.state.weatherData)
  }
  render() {
    return (
      <div>
          <h1>Hello world</h1>
      </div>
    );
  }
}

Скрин из консоли:

Answer 1

Если я правильно понял, вы хотите получить значение r.data при монтировании компонента? Но асинхронный запрос не успевает завершиться до монтирования компонента. И надо изменить state компонента после получения r.data

Вариант 1. Поместить getWeatherData внутрь App и делать setState внутри блока .then

.then((r) => {
    this.setState({
        weatherData: r.data
    })
}

Вариант 2. Использовать любую методику с единым хранилищем состояния flux/redux и т.д. и в блоке .then вызывать диспетчер с действием изменения города в App

Answer 2

Если не использовать никаких оберток а просто React, то логика для работы с начальным фетчем обычно примерно такая:

  1. Инициализируем чем-нибудь состояние скажем null.

    state = {weatherData: null}
    
  2. В ничего не отрисовываем если данных нет (можно конечно начальный каркас отрисовать если хочется).

    render(){
       if(this.state.weatherData === null){
         return null;
       }
    }
    
  3. В componentDidMount вызываем нашу асинхронную операцию операцию по получению данных, и когда она завершится соответственно меняем state;

    componentDidMount(){
        this.getWeatherData().then(weatherData => this.setState({weatherData: weatherdata})
    }  
    

Это самый простой подход для иллюстрации принципа. Он рабочий, но в сложных приложениях обычно поверх наворочено пара уровней абстракции вроде взаимодействия с хранилищем и ряд мелких ui-оптимизаций

READ ALSO
Чтение полученного значения JS

Чтение полученного значения JS

Всем привет, у меня есть скрипт, в нем метод, который получает responseСтрока вида:

236
обернуть все элементы определенного div

обернуть все элементы определенного div

У меня есть divпри помощи jquery или javascript обернуть все элементы внутри

313
Как поменять значение у одного свойства объекта?

Как поменять значение у одного свойства объекта?

Как вместо этого сделать копию объекта через spread оператор, и у копии поменять значение одного свойстваНужно поменять только date

279