48 votes

L'appel asynchrone dans componentWillMount se termine après la méthode de rendu

Je suis en train d'effectuer un appel asynchrone à une API dans le componentWillMount méthode. En effet, je voudrais l' render méthode à exécuter après la componentWillMount méthode que j'ai besoin de passer props de la composante dans mon render méthode.

Voici mon code :

class TennisSearchResultsContainer extends React.Component {
  componentWillMount () {
    // TODO: Build markers for the map
    // TODO: Check courtsResults object and database for tennis court
    this.courtsMarkers = this.props.courtsResults.map((court) => {
      return new google.maps.Marker({
        position: new google.maps.LatLng(JSON.parse(court.LOC).coordinates[1], JSON.parse(court.LOC).coordinates[0]),
        title: court.NAME,
        animation: google.maps.Animation.DROP
      });
    });
  }
  render () {
    return <TennisSearchResults criterias={this.props.criterias} courtsMarkers={this.courtsMarkers} />;
  }
}

Je ne comprends pas alors pourquoi mon render méthode semble ne pas attendre que l'appel asynchrone de terminer et de passer undefined accessoires pour mon enfant composant...

Suis-je le droit? Et que dois-je faire pour corriger cela? Qu'est-ce que la façon de gérer cela?

85voto

Todd Chaffee Points 1329

Vous pourriez avoir besoin de comprendre le javascript asynchrone comportement de mieux. Asynchrone signifie "ne pas attendre". Que la tâche va se passer dans l'arrière-plan et le code continuera à exécuter. Une bonne façon de gérer cela est de définir l'état de votre composant. Par exemple, lorsque vous entrez componentDidMount ensemble un loading etat true. Puis, quand votre asynchrone en fonction terminée, définissez cet état d' false. Dans votre render fonction, vous pouvez alors afficher un message "chargement..." ou les données.

Voici un code qui montre un exemple simplifié de l'extraction de données asynchrone et comment vous pourriez poignée de Réagir. Ouvrir les outils de développement de votre navigateur et regarder la sortie de la console pour comprendre la Réagir cycle de vie meilleure.

EDIT: le Code a été mis à jour pour utiliser la nouvelle Réagir Cycle de vie des recommandations en avril 2018. En résumé, j'ai remplacé componentWillMount avec la safer componentDidMount.

Il peut sembler inefficace de mise à jour de l'état après le composant a déjà monté, en tant que composante"FAITmonter " correctement implique. Toutefois, par les officiels de Réagir de la documentation sur componentDidMount:

"Si vous avez besoin de charger des données à partir d'un point de terminaison distant, c'est un bon endroit pour instancier la demande du réseau."

"Appelant setState() dans cette méthode va déclencher un supplément de rendu, mais il va se passer avant les mises à jour du navigateur à l'écran. Cela garantit que même si l' render() sera appelé à deux reprises dans ce cas, l'utilisateur ne voit pas l'état intermédiaire."

Voici l'exemple de code complet:

class MyComponent extends React.Component {
  constructor(props) {
    super();

    console.log('This happens 1st.');

    this.state = {
      loading: 'initial',
      data: ''
    };

  }

  loadData() {
    var promise = new Promise((resolve, reject) => { 
      setTimeout(() => {
        console.log('This happens 6th (after 3 seconds).');
        resolve('This is my data.');
      }, 3000);
    });

    console.log('This happens 4th.');

    return promise;
  }

  componentDidMount() {

    console.log('This happens 3rd.');

    this.setState({ loading: 'true' });
    this.loadData()
    .then((data) => {
      console.log('This happens 7th.');
      this.setState({
        data: data,
        loading: 'false'
      });
    });
  }  

  render() {

    if (this.state.loading === 'initial') {
      console.log('This happens 2nd - after the class is constructed. You will not see this element because React is still computing changes to the DOM.');
      return <h2>Intializing...</h2>;
    }


    if (this.state.loading === 'true') {
      console.log('This happens 5th - when waiting for data.');
      return <h2>Loading...</h2>;
    }

    console.log('This happens 8th - after I get data.');
    return (
      <div>
        <p>Got some data!</p>
        <p>{this.state.data}</p>
       </div>
    );
  }
}

ReactDOM.render(
  <MyComponent />,
  document.getElementsByClassName('root')[0]
);

Et voici l' exemple de travail sur CodePen.

Enfin, je pense que cette image de la moderne Réagir cycle de vie par Réagir responsable Dan Abramov est utile pour visualiser ce qui se passe et quand.

enter image description here

NOTER que de Réagir 16.4, ce cycle de vie diagramme a une petite inexactitude: getDerivedStateFromProps est maintenant également appelée après l' setState ainsi que forceUpdate. Voir cet article de l'officiel Réagir blog à propos de la Correction de bug pour getDerivedStateFromProps

Cette version interactive de Réagir diagramme de cycle de vie permet de sélectionner Réagir la version 16.04 avec les dernières comportement. Assurez-vous de cocher la case "Afficher moins fréquents cycles de vie" option.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X