1
votes

Le rendu est en cours d'exécution avant la fin de la méthode async. Comment puis-je passer des accessoires au composant à partir de ma méthode asynchrone?

Je ne souhaite pas transmettre les données de Firestore à mes composants. Mais la demande est asynchrone, donc je suis bloqué sur un problème lorsque ma méthode de rendu s'exécute avant d'obtenir les données de ma demande. Ainsi, lorsque le rendu s'exécute, la valeur pops est Null car l'état n'est pas encore défini. Aussi le composant pour une raison quelconque rend deux fois. Existe-t-il un meilleur moyen de gérer les trucs asynchrones?

J'ai déjà essayé de placer la requête sur Firestore à un endroit plus élevé (index.js) et de transmettre les données à l'application. J'ai essayé de faire une demande dans la méthode de rendu. J'ai essayé de placer la requête dans la fonction async et de l'appeler dans le constructeur pour y définir l'état. Même chose que l'appel de la méthode async.

class App extends Component {
constructor(props) {
    super(props);
    this.giveUsername = this.giveUsername.bind(this);

    const userId = firebase.auth().currentUser.email;
    this.giveUsername(userId);
}

async giveUsername(userId){
    let username;
    await firebase.firestore().collection('users').where('email', '==', userId).get().then((snapshot) =>{
        snapshot.docs.forEach(doc =>{
            console.log(`doc.data().username - ${doc.data().username}`);
            username = doc.data().username;
        });
    });
    this.setState( {
        userId : userId,
        username : username
    });
 }

render() {
    return (
      <div className='App'>
        <Header username={this.state.username}/>
        <NewTask userId={this.state.userId}/>
        <TaskList userId={this.state.userId}/>
      </div>
    );
}
}


0 commentaires

3 Réponses :


0
votes

Le rendu s'exécutera avant que vous n'obteniez vos données, c'est tout à fait normal et correct. Vérifier si les données sont nulles et afficher un message de chargement ou rien ( return null )


0 commentaires

0
votes

vous devez initialiser l ' état dans le constructeur pour que votre composant s'affiche correctement même sans données, et ajouter une clé loading pour savoir quand les données sont prêtes, et il le ferait être utile pour montrer un pinner

render() {
    return (
      <div className='App'>
        {this.state.loading 
         ? <span>Loading ... </span> 
         : (
             <Header username={this.state.username}/>
             <NewTask userId={this.state.userId}/>
             <TaskList userId={this.state.userId}/>
           )
        }
      </div>
    );
}

définir le chargement sur false lorsque les données sont prêtes:

async giveUsername(userId){
    ...
    this.setState( {
        userId : userId,
        username : username,
        loading: false
    });
 }

Rendu:

constructor(props) {
    super(props);
    state = {
      userId : 0,
      username : '',
      loading: true
    }
}

et la raison pour laquelle le composant rend twince est que l ' état change et c'est normal.


0 commentaires

0
votes

La chose générale à comprendre lorsque vous faites des demandes est que, il est prévu qu'il n'y aura pas de données au début de votre composant et vous ne pouvez rien faire à ce sujet.

La meilleure pratique consiste à laisser l'utilisateur sachez que les données sont en cours de chargement.

async giveUsername(userId){
    let username;
    await firebase.firestore().collection('users').where('email', '==', userId).get().then((snapshot) =>{
        snapshot.docs.forEach(doc =>{
            console.log(`doc.data().username - ${doc.data().username}`);
            username = doc.data().username;
        });
    });
    this.setState( {
        userId : userId,
        username : username,
        loaded: true
    });
 }

Ne récupérez pas les requêtes dans votre contrôleur! Utilisez componentDidMount

componentDidMount(){
    const userId = firebase.auth().currentUser.email;
    this.giveUsername(userId);
}

Puis enfin dans giveUsername

constructor(){
  this.state = {username: null, userId: null, loaded: false};
}
render() {
    return (
      <div className='App'>
        {
           !this.state.loaded ? <p>Loading...</p> : 

              <Header username={this.state.username}/>
              <NewTask userId={this.state.userId}/>
              <TaskList userId={this.state.userId}/>
        }
      </div>
    );
}

p >


0 commentaires