Не могу разобрать, почему не удается обратиться к части объекта на react.js

183
31 мая 2018, 17:00

Есть компонент на react.js. Есть URL: https://swapi.co/api/people - здесь лежит объект всех героев звездных войн. Не могу понять, почему могу вывести, например, их количество count {data.count} в renderPeople() и все ок - отображается на локалхосте. Но когда пишу, например, имя {data.results[0].name} (там, где className='people__item') - пишет property '0' of undefined. Но если я создаю глобальную переменную в componentDidMount() - window.name = data.results[0].name и потом использую ее в renderPeople() - то она выводится. Пишу console.log(this.state.data.results[0].name) в componentDidMount() - и тоже выводится, но в renderPeople() - нет. Сначала мне казалось, что я неправильно обращение к объекту делаю, но раз я могу вывести что нужно в componentDidMount, а в renderPeople() - нет, то дело не в обращении. Сейчас думаю - может, объект не успевает подгружаться? Как я понимаю, в жизненном цикле компонента сначала начинает выполняться render. Помогите разобраться, в какую сторону копать - в обращение к объекту или что-то другое.

Вот код:

import React from 'react'
class App extends React.Component {
constructor(props) {
  super(props)
  this.state = {
    data: [],
    isLoading: false,
  }
}
componentDidMount() {
  const xhr = new XMLHttpRequest();
  const URL = 'https://swapi.co/api/people';
  xhr.open('GET', URL, true);
  xhr.send();
  this.setState({ isLoading: true })
  xhr.onreadystatechange = () => {
    if (xhr.readyState !== 4) {
      return false
    }
    if (xhr.status !== 200) {
      console.log(xhr.status + ': ' + xhr.statusText)
    } else {
      this.setState({
        data: JSON.parse(xhr.responseText),
        isLoading: false,
      })
    }
    //window.arr = [];
    window.name = this.state.data.results[0].name;
    console.log(this.state.data.results[0].name);
    /*for (var i = 0; i < 10; i++) {
        window.arr[i] = this.state.data.results[i].name;
    }*/
    //console.log(window.arr);
    //console.log(window.arr[0]);
  }
}
renderPeople() {
  const { data, isLoading } = this.state
  if (isLoading) {
    return <img src='/i/preloader.gif' alt='загружаю...' />
  } else {
    return (
    <div className='people'>
        <h1 className = 'people__text'>Персонажи</h1>
        <p className = 'people__text'>Количество: {data.count}</p>
        <ul className = 'people__list'>
            <li className = 'people__item'>{}</li>
        </ul>
    </div>)
  }
}
render() {
  return (
    <div className='App'>
      <div className='people-list'>
        {this.renderPeople()}
      </div>
    </div>
  )
}
}
export default App
Answer 1

Проблема заключается в том, что в первый раз renderPeople вызывается до того, как завершится вызов ajax запроса.

Ошибок при обращении к data.count нет, так как объект data существует, и в случае обращения до завершения запроса count просто имеет значение undefined и никак не выводится.

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

В случае же с запросом к data.results[0], то results еще не заполнено, так как запрос еще не завершился и идет попытка обращения именно к этому незаполненному полю.

Проблемы можно избежать, если проверять заполнена ли data уже или нет.

READ ALSO
Адекватный счётчик времени fromNow moment.js

Адекватный счётчик времени fromNow moment.js

не получаться разобраться с библиотекой monetjs подскажите пожалуйстаНужно посчитать сколько времени прошло с определенного момента, то есть...

173
Ошибка при работе с Axios Vue.js

Ошибка при работе с Axios Vue.js

Здравтсвуйте, возникла проблема, при использовании Axios вместе с Vuejs

273
Загрузка файлов через ftp на Node js

Загрузка файлов через ftp на Node js

Есть приложение на node js которое копирует директорию и загружает её на сервер таким образом:

280