Redux/Firebase - 在状态中收到 uid 后组件不更新
Posted
技术标签:
【中文标题】Redux/Firebase - 在状态中收到 uid 后组件不更新【英文标题】:Redux/Firebase - Component not updating after uid is received in state 【发布时间】:2017-02-09 15:58:13 【问题描述】:我正在为我的 Redux 应用程序使用 Firebase 的身份验证 API。我有一个应用程序组件,应该在收到用户的 UID 身份验证时收到通知,并切换向用户显示哪个标头(登录标头或注销标头)。但是,在用户已经登录并重新访问主路由的情况下,当 UID 存储到应用程序状态时,我似乎无法让我的主应用程序重新呈现。
流程的轮廓是这样的:
在 routes/index.js 中: Firebase 的 onAuthStateChanged 观察者 识别用户是否已经登录,当主 路由负载。如果有用户,则调度操作以复制其 UID 从 Firebase 到我们的状态并将它们发送到“连接”页面。
在 actions.jsx 中: startLoginForAuthorizedUser 操作创建者 调度一个操作以使用新的 UID & 更新 auth reducer 将用户重新路由到“连接”。
在 reducers.jsx 中:“auth”状态更新为包含用户的 UID 允许组件根据 身份验证状态。
在 App.jsx 中: 无论出于何种原因,mapStateToProps 都没有收到 更新状态,即使用户已通过身份验证并且 Redux dev 工具显示使用新 UID 更新的状态。
最终结果是经过身份验证的用户可以按预期看到“连接”页面,但仍会看到已注销的标头。代码如下:
App.jsx
import React from 'react';
import connect from 'react-redux';
import * as actions from 'actions';
import HeaderLoggedOut from './HeaderLoggedOut';
import ModalOverlay from './ModalOverlay';
import MenuWrapper from './MenuWrapper';
import Header from './Header';
import Tabs from './Tabs';
export const App = React.createClass(
render()
const uid = this.props;
console.log("App.jsx: uid:", uid);
if(!uid)
return(
<div>
<HeaderLoggedOut />
<div className="tonal-main">
<div className="tonal-content">
this.props.children
</div>
</div>
<ModalOverlay />
</div>
);
return(
<MenuWrapper>
<Header />
<div className="tonal-content">
this.props.children
</div>
<Tabs />
</MenuWrapper>
);
);
const mapStateToProps = (state) =>
// state is not updated
return
uid: state.auth.uid
;
;
export default connect(mapStateToProps)(App);
路由器/index.js
import App from 'App.jsx';
import Connect from 'connect/Connect.jsx';
import firebase from 'app/firebase';
const store = require('store').configure();
firebase.auth().onAuthStateChanged((user) =>
if(user.emailVerified && user.uid)
store.dispatch(actions.startLoginForAuthorizedUser(user.uid));
else
browserHistory.push('/');
);
const requireLogin = (nextState, replace, next) =>
const currentUser = firebase.auth().currentUser;
if(!currentUser)
replace('/');
next();
;
const redirectIfLoggedIn = (nextState, replace, next) =>
const currentUser = firebase.auth.currentUser;
if(currentUser)
replace('/connect');
next();
;
export default (
<Router history= browserHistory >
<Route path="/" component= App >
<IndexRoute component= Landing onEnter= redirectIfLoggedIn />
<Route path="connect" component = Connect onEnter = requireLogin />
</Route>
</Router>
);
Actions.jsx
// ...actions, imports, etc...
export var startLoginForAuthorizedUser = (uid) =>
return (dispatch) =>
dispatch(login(uid));
dispatch(pushToRoute('/connect'));
;
;
export var login = (uid) =>
console.log('actions: logging in user with uid ', uid);
return
type: 'LOGIN',
uid
;
;
export var pushToRoute = (route) =>
browserHistory.push(route);
;
Reducer.jsx
const authInitialState =
uid: ""
;
export const authReducer = (state = authInitialState, action) =>
switch(action.type)
case 'LOGIN':
return
...state,
uid: action.uid
;
case 'LOGOUT':
return
...state,
uid: ""
;
default:
return state;
;
您的专家的任何帮助将不胜感激。这让我发疯了。
【问题讨论】:
【参考方案1】:经过令人尴尬的反复试验后,我想通了。对于将来想要同时使用 react-router
/react-router-dom
和 firebase 的 onAuthStateChanged()
观察者的其他人,只知道您必须将观察者代码保留在最顶层的组件中(在其中呈现您的ReactDOM.render()
中的提供商)。
如果您将它放在其他任何地方,它似乎无法正常工作,坦率地说,我不知道为什么。如果更熟悉 firebase 的人想要解释那里发生的事情以及为什么它可以在***组件中工作而不是在路由索引文件中工作,我相信它会对以后的人有所帮助。
【讨论】:
我不认为这是一种尴尬,而是向前迈进了一步!我花了 4 天时间弄明白,这是由于 ` 和 ' !以上是关于Redux/Firebase - 在状态中收到 uid 后组件不更新的主要内容,如果未能解决你的问题,请参考以下文章
无法在 firebase 重定向结果中使用 Redux 道具
React Redux Firebase 无法获取 firebase.storage
如何修复 React/Redux/Firebase 错误上传文件到存储
如何组合两个 Redux Firebase Cloud Firestore 查询?
React Redux Firebase - 使用 firestore 时,第一个文档的 isLoaded 仅为 false