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-domfirebase 的 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

HOC 反应 redux firebase。 (错误:上传文件需要 Firebase 存储)