4
votes

Comment passer l'état asynchrone aux accessoires de composant enfant?

Je suis nouveau pour réagir et j'essaie de récupérer des données à partir d'une API et de transmettre les données à un composant enfant. J'ai passé les données à l'état sur mon composant parent, cependant, lorsque je les transmets au composant enfant en tant qu'accessoires, il les enregistre comme un tableau vide. Je suis sûr qu'il y a quelque chose de simple que je néglige mais je ne sais pas quoi, mon code est ci-dessous

COMPOSANT PARENT

import React, {Component} from 'react';

class Child extends Component {
    initChild = () => {
        console.log(this.props.data); // returns empty array

        const properties = this.props.data.map(property => [property.name, property.lat, property.lng]);
    }

    componentDidMount = () => this.initChild();

    render () {
        return (
            <div>Test</div>
        )
    }
}

export default Child;

COMPOSANT ENFANT

import React, {Component} from 'react';
import Child from '../src/child';
import './App.css';

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
          properties: []
        }
    }

    getData = () => {
        fetch('url')
        .then(response => {
            return response.text()
        })
        .then(xml => {
            return new DOMParser().parseFromString(xml, "application/xml")
        })
        .then(data => {
            const propList = data.getElementsByTagName("propertyname");
            const latitude = data.getElementsByTagName("latitude");
            const longitude = data.getElementsByTagName("longitude");

            var allProps = [];

            for (let i=0; i<propList.length; i++) { 
                allProps.push({
                    name: propList[i].textContent,
                    lat: parseFloat(latitude[i].textContent), 
                    lng: parseFloat(longitude[i].textContent)
                });
            }

            this.setState({properties: allProps});
        });
    }

    componentDidMount = () => this.getData();

    render () {
        return (
            <div>
                <Child data={this.state.properties} />
            </div>
        )
    }
}

export default App;


0 commentaires

3 Réponses :


3
votes

Remplacez le componentDidMount de l'enfant par componentDidUpdate.

La méthode de cycle de vie componentDidMount est appelée une seule fois au début. Alors que la méthode de cycle de vie componentDidUpdate est appelée chaque fois qu'il y a un changement dans l'état de l'application. Étant donné que les appels API sont asynchrones, la fonction initChild () est déjà appelée une fois avant que les résultats de l'appel API ne soient transmis à l'enfant.


2 commentaires

Merci! cela a fait l'affaire, donc chaque fois qu'une fonction d'un composant enfant nécessite des données de manière asynchrone d'un autre composant, vous l'appelez avec componentDidUpdate?


Cela dépend de la façon dont vous utiliserez les accessoires. Mais dans ce cas, oui.



0
votes

Vous pouvez utiliser le rendu conditionnel

import React, {Component} from 'react';

class Child extends Component {
    initChild = () => {
        if(this.props.data){
          const properties = this.props.data.map(property => [property.name, property.lat, property.lng]);
        }        
    }

    componentDidMount = () => this.initChild();

    render () {
        return (
            <div>Test</div>
        )
    }
}

export default Child;


0 commentaires

0
votes

Si vous utilisez un composant basé sur une classe, utilisez la méthode componentDidUpdate

useEffect(() => {
    console.log(props.data);
   //Update child component state with props.data
  }, []);

Si vous utilisez un composant fonctionnel, utilisez useEffect

componentDidUpdate() {
   console.log(props.data);
   //Update child component state with props.data
}


0 commentaires