ReactJs:如何在呈现之前等待componentDidMount()完成?
如何在呈现之前等待async componentDidMount()完成 My app.jsx: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
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
}
谢谢你,这就成功了。我应该仔细阅读承诺:)在加载时与微调器组件很好地配对渲染是真实的相当整洁的解决方案谢谢,伟大的解决方案!