我正在使用react-router在反应式网络应用中实现firebase auth。
用户使用弹出式登录登录(在/登录)Facebook或Google,然后如果成功,我将路由到主应用程序(/)。在主应用程序组件中,我监听身份验证状态更改:
componentWillMount() {
this.authListener = this.authListener.bind(this);
this.authListener();
}
authListener侦听身份验证更改:
authListener() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('user changed..', user);
this.setState({
User: {
displayName: user.displayName
}
});
} else {
// No user is signed in.
browserHistory.push('/signin');
}
});
}
一切正常,除非我退出(并返回/登录)并使用脸书或谷歌再次登录。然后我收到一个错误说:
警告:setState(...):只能更新已安装或已安装 成分
我怀疑现在已卸载的先前登录状态应用程序中的onAuthStateChanged侦听器仍在运行。
有没有办法在卸载App组件时删除onAuthStateChanged侦听器?
答案 0 :(得分:17)
您设置的所有听众也需要拆除。
你的怀疑非常多。
您应该使用componentWillUnmount生命周期方法删除可能污染您的应用的任何剩余侦听器。
要清理听众,请参阅以下相关代码:
在authListener
函数中,您需要在组件内部保存对侦听器的引用(由于调用firebase.auth().onAuthStateChanged
而将其返回给您)。它将是一个钩子,它将取消引用侦听器并将其删除。
所以不要只是调用它,而是保存返回的值
this.fireBaseListener = firebase.auth().onAuthStateChanged ...
当您的组件卸载时,请使用以下代码:
componentWillUnmount() {
this.fireBaseListener && this.fireBaseListener();
this.authListener = undefined;
}
答案 1 :(得分:14)
我知道我迟到了,但这是一个基于钩子的解决方案:
React.useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged((user) => { // detaching the listener
if (user) {
// ...your code to handle authenticated users.
} else {
// No user is signed in...code to handle unauthenticated users.
}
});
return () => unsubscribe(); // unsubscribing from the listener when the component is unmounting.
}, []);
答案 2 :(得分:2)
@Justin因为onAuthStateChanged
返回功能所以你可以用它来清除监听器......
this.fireBaseListener = firebase.auth().onAuthStateChanged
docs:https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged
返回包含非null数组字符串
的非null firebase.Promise
答案 3 :(得分:0)
您可以像这样检查订阅的内容,而不是检查onAuthStateChanged()
内部的componentDidMount()
功能。
componentWillMount() {
//following line will help you to setState() but not required
let set = this
//this is our trick
this.unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (!user) {
//navigate to guest stack
//actually im using react-navigation
set.props.navigation.navigate('Guest');
} else {
//set current user to state
set.setState({
user: user,
loading: false
})
}
});
}
//What you have to do next is unsubscribe ;)
componentWillUnmount() {
this.unsubscribe();
}