Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ReactJs:如何在呈现之前等待componentDidMount()完成?_Reactjs_Firebase - Fatal编程技术网

ReactJs:如何在呈现之前等待componentDidMount()完成?

ReactJs:如何在呈现之前等待componentDidMount()完成?,reactjs,firebase,Reactjs,Firebase,如何在呈现之前等待async componentDidMount()完成 My app.jsx: constructor(props) { super(props); this.state = { loggedInUser: null, isAuthenticated: false, isAuthenticating: true }; } componentDidMount() { try { v

如何在呈现之前等待async componentDidMount()完成

My app.jsx:

constructor(props) {
    super(props);

    this.state = {
        loggedInUser: null,
        isAuthenticated: false,
        isAuthenticating: true
    };
}

componentDidMount() {
    try {
        var user = authUser();
        console.log('User: ' + user)
        if (user) {
            console.log('Is logged in: ' + this.state.loggedInUser)
            this.userHasAuthenticated(true);  
        }
    }
    catch(e) {
       alert(e);
    }
    this.setState({ isAuthenticating: false });
}

render() { 
   console.log('in render: ' + this.state.loggedInUser)
   // Should execute **after** authUser() in componentDidMount has finished  
   ...
}
componentDidMount调用此异步函数:

function authUser() {
    firebase.auth().onAuthStateChanged(function(user) {
        return user
    })
}
console.log('in render: ' + this.state.loggedInUser)

如何使呈现方法在componentDidMount中等待authUser()

在渲染之前不要等待
componentDidMount
完成,否则会误用库,请等待
authUser
完成

您可以通过将您的
isauthentication
状态属性与
承诺结合使用来实现这一点

function authUser() {
   return new Promise(function (resolve, reject) {
      firebase.auth().onAuthStateChanged(function(user) {
         if (user) {
            resolve(user);
         } else {
            reject('User not logged in');
         }             
      });
   });
}
您可以使用现有的
isauthentication
标志,如下所示:

componentDidMount() {
    authUser().then((user) => {
       this.userHasAuthenticated(true);
       this.setState({ isAuthenticating: false });
    }, (error) => {
       this.setState({ isAuthenticating: false });
       alert(e);
    });
}
然后在内部渲染:

render() {
   if (this.state.isAuthenticating) return null;
   ...
}

这将阻止将组件添加到DOM,直到
authUser
函数完成。

componentDidMount
将始终在第一次渲染后激发


使用
componentWillMount
或与第二次渲染一起使用,
setState
触发新渲染,并且componentWillMount总是在组件装载后触发,即组件正确渲染。

如果您不想渲染组件,使用自定义授权组件包装组件,如果用户未登录,则不呈现组件。
试图阻止调用
render
函数是不好的做法。

我认为这里的问题是
authUser
是异步的。为了以干净的方式处理异步响应,我将使用承诺。我不知道firebase API,但显然支持以下承诺:

否则,您可以使用bluebird之类的库并修改authUser函数以返回承诺:

如果您不熟悉承诺,您应该首先阅读基础知识:

您的
authUser()
函数似乎设置不正确。您在回调中返回user对象,但函数本身没有返回任何内容,因此
var user=authUser()将始终返回未定义的

您需要将
authUser()
更改为调用回调函数或返回
Promise
,当用户从Firebase返回时,该函数将解析。然后,在解析承诺或执行回调后,将身份验证状态设置为您的状态。在
render()
函数中,如果身份验证尚未完成,则返回
null

带回调的异步函数:

function authUser(callback) {
    firebase.auth().onAuthStateChanged(function(user) {
        callback(user);
    })
}
将回调与组件一起使用:

componentDidMount() {
    try {
        authUser(function(user) {
            console.log('User: ' + user)
            if (user) {
                console.log('Is logged in: ' + this.state.loggedInUser)
                this.userHasAuthenticated(true);  
                this.setState({ isAuthenticating: false });
            }
        });
    }
    catch(e) {
       alert(e);
    }
}

render() { 
   console.log('in render: ' + this.state.loggedInUser)
   if (this.state.isAuthenticating === true) {
       return null;
   }
   // Rest of component rendering here
}

谢谢你,这就成功了。我应该仔细阅读承诺:)在加载时与微调器组件很好地配对渲染是真实的相当整洁的解决方案谢谢,伟大的解决方案!