Жизненный цикл компонента React.js, поведение состояний и асинхронная природа JavaScript - PullRequest
0 голосов
/ 22 октября 2018

У меня проблема с ожидаемым результатом и фактическим результатом.Несмотря на то, что методы fetchData() и fetchnumberOfCommits() вызываются из componentWillMount(), в массиве нет данных.Но в конце метод рендеринга вызывается дважды, где массив получает данные из API.Я вызвал метод setState() в обоих вышеупомянутых методах, где он вызывает метод рендеринга.Моя проблема в том, почему массив не получает данные, как только эти два метода вызваны?и в какой момент массив получает данные?

Пример кода

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

Как указано выше, вы должны удалить его из componentWillMount, так как он устарел с 16.3.Должен быть в состоянии поместить его в componentDidMount, и он будет работать для вас.

0 голосов
/ 28 октября 2018

Я также изменил с componentWillMount() на componentDidMount(), но у меня возникла та же проблема.Причиной тому была асинхронная природа JavaScript.Когда вы используете обещания, он не ждет, пока вы не получите результаты от вызова API.Он просто запускает коды в порядке, сохраняя обещание, пока не получит данные.По этой причине я получил пустой массив, даже несмотря на то, что была вызвана функция.

Вы можете использовать async/await для синхронизации кода, а затем он будет ждать, пока вы не получите результаты от вызова API.Если вы запустите следующий пример кода, вы увидите результаты в консоли, где fetchData1() дает пустой массив, а fetchData2() - массив с данными. Кроме того, если вы хорошо изучите консоль, вы увидите, что когда *Функция 1008 * называется триггером метода render().

import React, { Component } from 'react';

class App extends Component {
  constructor(){
    console.log('This is from constructor');
    super();     
    this.state={
      repositories:[],
  }  
  }
  componentDidMount(){
    console.log('This is from componentDidMount');
    this.fetchData1();
    this.fetchData2();
  }
  fetchData1(){
        console.log('This is function is using promises');
        fetch('https://api.github.com/users/94ju/repos').then(results => results.json()).then(repositories =>this.setState({ 
          repositories
        })).then( 
          console.log( this.state.repositories),
          console.log(this.state)
        ) 
        console.log('End of using promises')

  }
  async fetchData2(){
    console.log('This is function is using async-await');
    const check =await fetch('https://api.github.com/users/94ju/repos');
    const checkjson =await check.json();
    console.log('Before setState');
    this.setState({ async_repositories: checkjson });
    console.log( this.state.async_repositories);
    console.log(this.state);
    console.log('End of async-await');
}
  render() {
    console.log("Starting render function");
    const repo =this.state;
    console.log(repo);
    console.log('Ending render function');
    return (
      <div>

      </div>
    );

  }
}

export default App;
0 голосов
/ 22 октября 2018

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

componentWillMount() устарел в Реакте 16.3.Вы должны использовать componentDidMount() для извлечения данных, и вы должны ожидать, что ваш компонент будет отображаться хотя бы один раз, прежде чем ваши данные будут извлечены, поэтому вам нужно будет отобразить либо null, либо состояние загрузки, прежде чем данные будут извлечены.Я привел пример того, как вы можете проверить, правильно ли он был загружен, и показать сообщение о загрузке.

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      check: true,
      repositories: [],
      commits: [],
    };
  }

  componentDidMount() {
    this.fetchData();
    this.fetchNumberOfCommits();
  }

  fetchData() { /*...*/ }
  fetchNumberOfCommits() { /*...*/ }

  isLoaded() {
    return this.state.respositories.length > 0;
  }

  render() {
    const { repositories } = this.state;

    if(isLoaded) {
      return repositories.map(repo => {
        return (
          <Api
            repo={repo.name}
            createdDay={repo.createdDay} 
          />
        );
      });
    }

    return <h1>Loading repos...</h1>;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...