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?
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:
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.
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);
});
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 username
img
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.