web-dev-qa-db-fra.com

React Composant enfant non mis à jour après un changement d'état du parent

J'essaie de créer un composant ApiWrapper de Nice pour renseigner des données dans divers composants enfants. D'après tout ce que j'ai lu, cela devrait fonctionner: https://jsfiddle.net/vinniejames/m1mesp6z/1/

class ApiWrapper extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      response: {
        "title": 'nothing fetched yet'
      }
    };
  }

  componentDidMount() {
    this._makeApiCall(this.props.endpoint);
  }

  _makeApiCall(endpoint) {
    fetch(endpoint).then(function(response) {
      this.setState({
        response: response
      });
    }.bind(this))
  }

  render() {
    return <Child data = {
      this.state.response
    }
    />;
  }
}

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: props.data
    };
  }

  render() {
    console.log(this.state.data, 'new data');
    return ( < span > {
      this.state.data.title
    } < /span>);
  };
}

var element = < ApiWrapper endpoint = "https://jsonplaceholder.typicode.com/posts/1" / > ;

ReactDOM.render(
  element,
  document.getElementById('container')
);

Mais pour une raison quelconque, il semble que le composant enfant ne soit pas mis à jour lorsque l'état parent change.

Est-ce que j'ai râté quelque chose?

76
Vinnie James

Votre code pose deux problèmes.

L'état initial de votre composant enfant est défini à partir des accessoires.

this.state = {
  data: props.data
};

Citant ceci SO SO :

Passer l'état initial à un composant en tant que prop est un anti-motif car la méthode getInitialState (dans notre cas, le constuctor) n'est appelée que lors du premier rendu du composant. Jamais plus. Ce qui signifie que si vous refaites le rendu de ce composant en passant une valeur différente en tant que prop, le composant ne réagira pas en conséquence, car le composant conservera l'état depuis la première fois, il a été rendu. C'est très sujet aux erreurs.

Donc, si vous ne pouvez pas éviter une telle situation, la solution idéale consiste à utiliser la méthode componentWillReceiveProps pour écouter les nouveaux accessoires.

Ajouter le code ci-dessous à votre composant enfant résoudra votre problème avec le rendu du composant enfant.

componentWillReceiveProps(nextProps) {
  this.setState({ data: nextProps.data });  
}

Le deuxième problème concerne le fetch.

_makeApiCall(endpoint) {
  fetch(endpoint)
    .then((response) => response.json())   // ----> you missed this part
    .then((response) => this.setState({ response }));
}

Et voici un violon qui fonctionne: https://jsfiddle.net/o8b04mLy/

158
Yadhu Kiran

Il y a certaines choses que vous devez changer.

Lorsque fetch obtient la réponse, ce n'est pas un JSON. Je cherchais comment puis-je obtenir ce JSON et j'ai découvert cela lien .

De l'autre côté, vous devez penser que la fonction constructor n'est appelée qu'une fois.

Donc, vous devez changer la façon dont vous récupérez les données dans le composant <Child>.

Ici, j'ai laissé un exemple de code: https://jsfiddle.net/emq1ztqj/

J'espère que ça aide.

0
slorenzo