reactjs - React Redux Firebase - onAuthStateChanged 延迟阻止使用生命周期方法
问题描述
我正在 React Redux 应用程序中实现 Firebase 身份验证。
问题: 我遇到了一个问题,阻止我使用 React 的组件生命周期方法来支持条件渲染。
在页面之间导航时,当每个页面/组件加载时,初始cUser(当前用户)状态为 null。这是因为在等待 Firebase 的 'onAuthStateChanged' 方法解析和在 Redux 中更新cUser(当前用户)状态时会有一点延迟。组件在状态有机会与当前用户更新之前加载。这并不奇怪,因为这是一个异步过程。
问题: 处理这个问题的最佳方法是什么?
有很多方法可以解决这个问题,但使用组件生命周期方法会更有效。
我已经看到 2016 年的相关帖子指示检查 localStorage,但是在访问 localStorage 时,似乎没有任何与 Firebase 相关的内容。我假设 Firebase 不再将用户数据存储在 localStorage 中。
代码:
我的 App 组件调用“onAuthStateChanged”Firebase 方法。
import React, { Component } from 'react';
import { BrowserRouter, Route } from 'react-router-dom';
import { connect } from 'react-redux';
import { firebase } from '../firebase';
import * as actions from '../actions';
import '../styles/styles.css';
import { LOBBY, HISTORY, TOPS, LANDING, SIGN_UP, SIGN_IN, FORGOT_PASSWORD, ACCOUNT, SIGN_OUT } from '../config/routes';
import Header from './Header';
import Footer from './Footer';
import Lobby from './Lobby';
import History from './History';
import Tops from './Tops';
import Landing from './registration/Landing';
import SignIn from './registration/SignIn';
import SignUp from './registration/SignUp';
import SignOut from './registration/SignOut';
import Account from './Account';
import ForgotPassword from './registration/ForgotPassword';
class App extends Component {
componentDidMount() {
console.log(Object.keys(localStorage));
const { signOutUser, updateUserAuth } = this.props;
firebase.auth.onAuthStateChanged((authUser) => {
if (authUser) {
updateUserAuth(authUser);
} else {
signOutUser();
}
});
}
checkAuth() {
if (this.props.cUser) {
return <Header />;
}
return null;
}
render() {
console.log('cUser: from APP', this.props.cUser);
return (
<div className="lightGray">
<div className="container ">
<BrowserRouter>
<div>
{this.checkAuth()}
<Route exact path={LOBBY} component={Lobby} />
<Route exact path={HISTORY} component={History} />
<Route exact path={TOPS} component={Tops} />
<Route exact path={LANDING} component={Landing} />
<Route exact path={SIGN_UP} component={SignUp} />
<Route exact path={SIGN_IN} component={SignIn} />
<Route exact path={SIGN_OUT} component={SignOut} />
<Route exact path={FORGOT_PASSWORD} component={ForgotPassword} />
<Route exact path={ACCOUNT} component={Account} />
<Footer />
</div>
</BrowserRouter>
</div>
</div>
);
}
}
function mapStateToProps({ cUser }) {
return { cUser };
}
export default connect(mapStateToProps, actions)(App);
更新当前用户状态的操作。
export const updateUserAuth = user => async (dispatch) => {
try {
const payload = {
displayName: user.displayName,
email: user.email,
emailVerified: user.emailVerified,
refreshToken: user.refreshToken,
userId: user.uid,
};
return dispatch({ type: CURRENT_USER, payload });
} catch (error) {
console.log('error: ', error);
return error;
}
};
cUser(current user) 在 Account 页面上将始终为 null。
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';
class Account extends Component {
componentWillMount() {
if (this.props.cUser) {// always null
this.props.getUserData(this.props.cUser.idToken);
}
}
render() {
return (
<div className="">
<div className="row valign-wrapper section">
<h1 className=" bigHeader">Account</h1>
<div className="col s2 right-align" />
</div>
</div>
);
}
}
function mapStateToProps({ cUser }) {
return { cUser };
}
export default connect(mapStateToProps, actions)(Account);
火力基地实施
import firebase from 'firebase/app';
import 'firebase/auth';
const prodConfig = {
apiKey: 'xxxx',
authDomain: 'xxx',
databaseURL: 'xxx',
projectId: 'xxx',
storageBucket: 'xxx',
messagingSenderId: 'xxx',
};
const devConfig = {
apiKey: 'xxxx',
authDomain: 'xxx',
databaseURL: 'xxx',
projectId: 'xxx',
storageBucket: 'xxx',
messagingSenderId: 'xxx',
};
const config = process.env.NODE_ENV === 'production'
? prodConfig
: devConfig;
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
export const auth = firebase.auth();
解决方案
通过将 userId 存储在 localStorage 中解决了这个问题。
firebase.auth.onAuthStateChanged((authUser) => {
if (authUser) {
localStorage.setItem('userId', authUser.uid);
updateUserAuth(authUser);
} else {
localStorage.removeItem('userId');
signOutUser();
}
});
推荐阅读
- c# - 我怎样才能提高我的“比较”方法效率?
- reactjs - 在 Android 上弹出的 Expo 项目上运行 Realm 并出现错误
- java - 将带有自定义实现方法的通用枚举作为参数传递
- php - 数据附加到产生不正确结果的 php Implode 语句
- linux - Snap 无法运行,snap.tar.gz 已经退出
- java - IDEA intellij 如何停止常量重新格式化?
- android - gradle(右侧)中的Android studio 4.2.1 siginig报告无法找到
- powershell - 使用 Powershell 将文件上传到 Sharepoint Online (Microsoft 365)(选项 3 - 使用 System.Net.WebClient)
- reactjs - TypeError:无法读取注销按钮上未定义链接的属性“推送”
- javascript - svg 带双边框的多边形