Vraag Asynchrone aanroep in component WillMount eindigt na weergavemethode


Ik probeer een asynchrone aanroep naar een API uit te voeren in de methode componentWillMount. Ik zou inderdaad de render methode om na de component componentWillMount uit te voeren als ik moet slagen props naar het onderdeel in mijn render methode.

Hier is mijn 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} />;
  }
}

Ik begrijp dan niet waarom mijn rendermethode lijkt te wachten op de asynchrone aanroep om te voltooien en niet-gedefinieerde rekwisieten door te geven aan mijn onderliggende component ...

Heb ik gelijk? En wat moet ik doen om dat op te lossen? Wat is de manier om hiermee om te gaan?


20
2018-04-09 21:40


oorsprong


antwoorden:


Mogelijk moet u Javascript async-gedrag beter begrijpen. Async betekent "niet wachten". Dat de taak op de achtergrond zal plaatsvinden en andere code zal blijven uitvoeren. Een goede manier om dit te beheren, is om de status van je component in te stellen. Bijvoorbeeld wanneer u invoert componentDidMount stel een loading stel in op true. Wanneer uw asynchroonfunctie is voltooid, stelt u die status in op false. In uw render functie kunt u vervolgens een bericht "loading ..." of de gegevens weergeven.

Hier is een code die een vereenvoudigd voorbeeld toont van het ophalen van data-async en hoe je dat in React aankan. Open de ontwikkelaarstools in uw browser en bekijk de console-uitvoer om de React-levenscyclus beter te begrijpen.

EDIT: Code is bijgewerkt om de nieuwe React Lifecycle-aanbevelingen vanaf april 2018 te gebruiken. Kort samengevat heb ik deze vervangen componentWillMount met de veiliger componentDidMount.

Het lijkt misschien inefficiënt om de status bij te werken na de component is al gemonteerd, als 'component'DEEDmount 'correct betekent. Echter, per officiële React-documentatie op componentDidMount:

"Als u gegevens van een extern eindpunt moet laden, is dit een goede plaats om het netwerkverzoek te converteren."

"Roeping setState() in deze methode wordt een extra rendering geactiveerd, maar dit gebeurt voordat de browser het scherm bijwerkt. Dit garandeert dat hoewel het render() wordt in dit geval twee keer gebeld, de gebruiker ziet de tussentoestand niet. "

Hier is de complete voorbeeldcode:

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]
);

En hier is het werkend voorbeeld op CodePen.

Tot slot denk ik dat dit beeld van de moderne React-levenscyclus van React -onderhouder Dan Abramov nuttig is om te visualiseren wat er gebeurt en wanneer.

enter image description here

LET OP dat dit lifecycle-diagram uit React 16.4 een kleine onnauwkeurigheid heeft: getDerivedStateFromProps wordt nu ook na genoemd setState net zoals forceUpdate. Bekijk dit artikel van de officiële React-blog over de Bugfix voor getDerivedStateFromProps 

Deze interactieve versie van het levenscyclusdiagram van React kunt u React versie 16.04 selecteren met het nieuwste gedrag. Zorg ervoor dat u de optie "Toon minder vaak voorkomende levenscycli" aanvinkt.


42
2018-04-09 21:48