首页 > 解决方案 > 渲染在异步方法结束之前运行。如何从我的异步方法将道具传递给组件?

问题描述

我需要将数据从 firestore 传递到我的组件中。但是请求是异步的,所以在我从请求中获取数据之前,当我的渲染方法运行时,我遇到了问题。因此,当渲染运行时,pops 值为 Null,因为尚未定义状态。由于某种原因,组件也会渲染两次。有没有更好的方法来处理异步的东西?

已经尝试过将请求放到更高位置的firestore(index.js)并将数据向下传递给应用程序。试图在渲染方法中发出请求。试图将请求放在异步函数中并在构造函数中调用它以在那里设置状态。与调用异步方法相同。

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>
    );
}
}

标签: javascriptreactjsfirebasegoogle-cloud-firestore

解决方案


您应该初始化state构造函数中loading

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

当数据准备好时设置为loadingfalse

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

使成为 :

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>
    );
}

组件呈现双胞胎的原因是因为它state正在发生变化,这是正常的。


推荐阅读