web-dev-qa-db-fra.com

Comment utiliser l'API fetch () dans React to setState

J'essaie d'écrire un composant dans React qui utilisera l'API fetch () pour obtenir les données d'un site Web, puis avec setState pour définir un état égal à celui-ci, puis restituer le rendu final. Mon code ressemble à ceci:

import React from 'react';

export default class Test extends React.Component {
    constructor(props){
        super(props);
        this.state = {apiInfo: 'default'};
    }

    componentDidMount(){
        fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent').then(
            function(response){
                return response.json();
            }
            ).then(function(jsonData){
                return JSON.stringify(jsonData);
            }
            ).then(function(jsonStr){
                this.setState({apiInfo: jsonStr});
                console.log(jsonStr);
            });
    }

    render(){
        return(
                <tr>
                    <td>{this.state.apiInfo}</td>
                </tr>
        );
    }
}

Cependant, cela entraîne une erreur indiquant que je ne parviens pas à définir un état non défini. Je finis par rendre 'default' sur mon HTML. Qu'est-ce que je fais exactement mal ici?

2
albert

Votre message d'erreur vous dit exactement quel est le problème:

impossible de définir l'état d'un indéfini

Vous essayez donc d'appeler setState en tant que méthode d'un objet qui n'existe pas à ce stade. En tant que propriété de quel objet essayez-vous d'appeler setState en tant que méthode?

this.setState ({apiInfo: jsonStr});

Oui, c’est votre this qui pose problème. Au moment où vous essayez de l’appeler - c’est-à-dire dans une .then() d’un appel fetch - this est en fait non défini. Vous pouvez le voir dans Chrome Devtools:

 Chrome Devtools shows this=undefined Je crains que this ne soit un client glissant en JavaScript; sa valeur peut (et change) en fonction du contexte actuel de votre application.

Il existe plusieurs façons de contourner ce problème. Un moyen légèrement maladroit (mais cela fonctionne!) Consiste à capturer votre valeur this avant de saisir votre appel .fetch () et de l’affecter à une autre variable. Vous verrez souvent les variables that ou self utilisées à cette fin, mais ce ne sont que des conventions. Vous pouvez appeler la variable comme vous le souhaitez.

Voici comment j'ai retravaillé votre méthode composantDidMount () en capturant this en that et en appelant that dans la fonction .then():

componentDidMount() {
    const that = this;
    fetch("https://fcctop100.herokuapp.com/api/fccusers/top/recent")
        .then(function(response) {
            return response.json();
        })
        .then(function(jsonData) {
            return JSON.stringify(jsonData);
        })
        .then(function(jsonStr) {
            that.setState({ apiInfo: jsonStr });
            console.log(jsonStr);
        });
}

Si vous êtes à l'aise avec les fonctions de flèche, une autre méthode consiste à remplacer votre appel de fonction "normal" par un autre, comme suit:

.then(jsonStr => {
    this.setState({ apiInfo: jsonStr });
    console.log(jsonStr);
});

La variable this d'une fonction de flèche est toujours la this définie par son parent.

6
ChillyPenguin

Cela signifie que setState n'est pas défini car vous y accédez dans le mauvais contexte. Vous pouvez soit convertir la fonction en une fonction de flèche ou la lier au bon contexte. Ici est un article décrivant Quand et pourquoi lions-nous à la méthode du composant React.

Dans votre code, le changement qui peut être fait est soit le contraignant

.then(function(jsonStr){
          this.setState({apiInfo: jsonStr});
          console.log(jsonStr);
      }.bind(this));

ou en utilisant la fonction flèche

.then((jsonStr)=>{
          this.setState({apiInfo: jsonStr});
          console.log(jsonStr);
      });
1
illiteratewriter
 componentDidMount() {
    fetch('https://fcctop100.herokuapp.com/api/fccusers/top/recent')
      .then(response => response.json())
      .then(data => this.setState({ apiInfo: data }));
  }

Dans votre fonction de rendu, vous ne pouvez pas simplement faire this.state.apiInfo. Ces données sont un tableau d'objets, chaque objet ayant des clés telles que usernameimg et plus. Vous pouvez voir cela si vous console.log(this.state.apiInfo) dans la fonction render et en dehors de return

Pour accéder aux valeurs de chaque tableau et les afficher à l'intérieur des tableaux, vous pouvez utiliser map dans votre tableau apiInfo.

render() {
const { apiInfo } = this.state;
apiInfo && console.log(apiInfo.map(item => item.img));
return (
  <div>
    {apiInfo &&
      apiInfo.map(item =>  <div> {item.img} </div> )}
  </div>
);
}

L'API de récupération native fournie avec le navigateur utilise JavaScript qui promet de résoudre la réponse asynchrone.

Une fois les données récupérées, elles seront stockées dans l’état local avec la méthode this.setState () de React. Ensuite, la méthode render () se déclenchera à nouveau et vous pourrez afficher les données extraites.

Les fonctions fléchées ont été introduites dans ES6 et une fonction fléchée n'a pas son propre contexte et utilisera la même this que le contexte dans lequel elle a été définie. Nous pouvons utiliser ce fait et transmettre une fonction de flèche au rappel.

0
Omar