Json Data не отображается в классе ReactJS после установки его состояния с помощью метода библиотеки axios?

Я пытаюсь прочитать данные JSON с помощью метода axios.get() функции библиотеки axios. Он отлично работает и регистрирует правильное имя пользователя в консоли и правильно устанавливает состояние переменной пользователя. Но когда я пытаюсь отобразить тот же объект в методе рендеринга ( ) он перестает работать. Ссылка на CODE на codepen .

class TableData extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      users:[],
      count: 0
    };
  }
  componentDidMount() {
    axios
      .get(`https://fcctop100.herokuapp.com/api/fccusers/top/recent`)
      .then(response => {
        this.setState({ users: response.data });
        console.log(this.state.users[2].username);
      });
  }
  render() {
    return (
      <div>Hello {this.state.users[2].username}</div>
    );
  }
}
ReactDOM.render(<TableData />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.12.0/axios.min.js"></script>
<div class="container" id="container">

</div>

URL-адрес возвращаемого объекта данных JSON типа

Object {
  alltime: 388,
  img: "https://avatars3.githubusercontent.com/u/36005?v=3",
  lastUpdate: "2017-10-17T08:05:51.276Z",
  recent: 124,
  username: "korzo"
}

Пожалуйста, помогите мне.


person Kartikey Singh    schedule 27.10.2017    source источник


Ответы (2)


Существует период времени, когда this.state.users является пустым массивом. Поэтому, когда ваша функция рендеринга обращается к this.state.users[2].username, this.state.users[2] может быть неопределенным, вызывая исключение. Вам просто нужно изменить функцию рендеринга, чтобы обрабатывать случай, когда массив пуст.

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

class TableData extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      users:[],
      count: 0
    };
  }
  componentDidMount() {
    axios
      .get(`https://fcctop100.herokuapp.com/api/fccusers/top/recent`)
      .then(response => {
        this.setState({ users: response.data }, function () {
          console.log(this.state.users[2].username);
        });
      });
  }
  render() {
    return (
      <div>Hello {this.state.users[2] && this.state.users[2].username}</div>
    );
  }
}
ReactDOM.render(<TableData />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.12.0/axios.min.js"></script>
<div class="container" id="container">

</div>

person Nicholas Tower    schedule 27.10.2017
comment
Просто чтобы быть точным на 100%: setState может откладывать обновления состояния, но это не всегда асинхронно. см.: twitter.com/acdlite/status/817075742915690496 - person marzelin; 27.10.2017
comment
@marzelin Спасибо за разъяснение :) - person Nicholas Tower; 27.10.2017

Метод render пытается отобразить this.state.users[2].username, который является undefined при монтировании компонента.

Ваш метод рендеринга должен быть примерно таким, чтобы рендерить только тогда, когда массив this.state.users имеет 2 элемента или более.

render() {
  return this.state.users.length > 1 ? (
    <div>Hello {this.state.users[2].username}</div>
  ) : null;
}

Кроме того, я не думаю, что console.log(this.state.users[2].username); должен возвращать правильные данные, потому что setState является асинхронным.

person Naisheel Verdhan    schedule 27.10.2017