1
votes

La récupération des données sur le composant a été montée avec async wait n'attend pas

J'essaie d'obtenir des données sur componentDidMount pour définir l'état dans react.

J'utilise asyn await sur componentdidMount, récupère des données, attend pour cela, et quand c'est fait, définit mon état sur les données. p >

Je suis exactement le même modèle dans cet article: https://medium.com/front-end-weekly/async-await-with-react-lifecycle-methods-802e7760d802

ceci est ma méthode componentDidMount: p>

render() {

console.log('here:', this.state)

return (
  <React.Fragment>
    <div className="red ba">Hella!</div>
    <List photographers={this.state.photographers}/>
  </React.Fragment>
  )
}

puis dans ma méthode de rendu, j'essaye d'utiliser la valeur d'état .. mais son indéfini:

  const url = "http://localhost:3001";
  const opts = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query })
  };
  await fetch(url, opts)
    .then(res => res.json())
    .then(data => this.setState({
      photographers: data
    }))
    .catch(console.error);
}

J'ai utilisé asunc await plusieurs fois avant, je sais comment cela fonctionne, mais pourquoi est-ce que cela ne fonctionne pas? merci!


1 commentaires

Vous n'avez pas besoin d'utiliser await dans votre exemple de code pour componentDidMount car vous n'utilisez jamais le résultat dans la méthode elle-même. De plus, componentDidMount se déclenche après que le composant ait été réellement monté sur le DOM. Ainsi, le premier rendu a déjà eu lieu. Et ce premier rendu verrait évidemment l'état initial avant que quoi que ce soit ne soit récupéré.


3 Réponses :


1
votes

Vous devez supprimer les méthodes .then () .catch (), elles renvoient des promesses, à la place, vous devez faire componentDidMount async et chercher en attente

constructor(props) {
    super(props)
    this.state = {
      photographers: []
    }
  }

async componentDidMount() {
  const url = "http://localhost:3001";
  const opts = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query })
  };
  try {
    const response = await fetch(url, opts)
    if (!response.ok) {
      throw Error(response.statusText);
    }
    const json = await response.json();
    console.log(json)
    this.setState({ photographers: json });
  } catch(error) {
    console.log(error)
  }
}


9 commentaires

J'ai essayé votre solution, mais toujours sur ma méthode de rendu lorsque j'essaye de console.log, l'état est nul @onuriltan


pouvez-vous objet json console.log avant this.setState? Je suppose que votre objet de requête est manquant, d'où vient-il?


Non, je ne peux rien enregistrer dans le componentdidMount, mais dans le constructeur oui .. ma requête est en haut du fichier et son correct. @onuriltan


oui l'erreur est qu'il a essayé de lire les photographes à partir de l'état .. mais son nul ... car il a été proposé d'être défini sur le composant a été monté après avoir récupéré @onuriltan


Je veux dire dans la console de votre navigateur .. pas l'état du composant


Non, il n'y a pas d'erreurs dans la console du navigateur .. l'application s'arrête car elle essaie de mapper sur l'état, mais son null, donc il dit "Impossible de lire la propriété 'map' de null" @onuriltan


vous devriez donc cocher si (this.state. photographers) devant le photographers.map (photographe => {...}), car il est initialement nul, ou rendre les photographes initiaux état comme un tableau vide


Ok ... mais cette partie est à l'intérieur d'un autre composant ... je passe les photographes comme accessoires, c'est moche de devoir vérifier si ces accessoires existent ... si je les passe, ils devraient exister ... non? @onuriltan


continuons cette discussion dans le chat .



1
votes

Voici comment fonctionne le javascript asynchrone, le code fonctionnera pour se terminer, qu'est-ce que cela signifie, c'est que pendant que vous exécutez une requête réseau et que vous avez écrit await dans componentDidMount, rien du code suivant ne s'arrêtera et attendra, tout continuera comme d'habitude ( et lorsque la requête réseau est terminée, le code dans le code then sera exécuté), notez qu'attendre est juste un moyen plus simple d'écrire puis des blocs (rien n'attend réellement)

car vous ne pouvez pas arrêter le rendu avec await, vous devrait gérer lorsque les données ne sont pas là, montrant généralement un écran de chargement, ce que vous pouvez faire est quelque chose comme ceci:

// You should initialise the photographers in the state to be null
render() {

console.log('here:', this.state)

return this.state.photographers !== null ? (
  <React.Fragment>
    <div className="red ba">Hella!</div>
    <List photographers={this.state.photographers}/>
  </React.Fragment>
  ) : (<div>Loading...</div>)
}


0 commentaires

0
votes

Vous essayez de combiner les deux syntaxes pour les appels asynchrones - async / await et .then (). catch () Tenez-vous-en à un.

Personnellement, je préfère mettre mon code asynchrone dans une fonction différente et l'utiliser dans componentDidMount ()

const fetchPhotographers = () => {  
  const url = "http://localhost:3001";
  const opts = {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query })
  };
  fetch(url, opts)
    .then(res => res.json())
    .then(data => this.setState({
      photographers: data
    }))
    .catch(console.error);
}

componentDidMount() {
 fetchPhotographers()
}


1 commentaires

Si cela ne fonctionne pas, il doit y avoir un problème avec une autre partie de votre code. Alors, ajoutez le code pour l'ensemble du composant ici.