React / Redux / Firebase:状态更新,但组件不重新渲染

时间:2016-10-31 01:55:50

标签: reactjs firebase-authentication react-redux

我正在尝试使用Firebase的电子邮件验证API。我有反应路由器捕获传入令牌,调度动作以验证令牌是否有效,然后获取当前用户的信息以存储到状态。使用Chrome的Redux devTools,看起来状态正在更新,但组件不会重新渲染。据我所知,我没有改变状态,所有对reducer对象的引用都被正确命名。

以下是一些代码:

Verify.jsx

// The component the user lands on to verify email.
// Stateless - verification is handled by react-router dispatching action.

import React from 'react';
import * as Redux from 'react-redux';
import * as actions from 'actions';

import Alert from 'helpers/Alert';

export const Verify = React.createClass({

    render(){

        return(
            <div>
                <Alert
                    type="warning"
                    title="Verifying E-Mail"
                    message={(
                        <div>
                            <p>One moment please while we verify your e-mail...</p>
                            <i className="fa fa-cog fa-spin fa-3x fa-fw float-center"></i>
                        </div>
                    )}
                />
                <div className={`auth-content blur`}>

                </div>
            </div>
        );
    }
});

export default Redux.connect()(Verify);

Actions.jsx

export const verifyEmailWithCode = (oobCode) => {
    return (dispatch) => {
        firebase.auth().applyActionCode(oobCode).then((success) => {
            // action code valid, add user to our database and send them to the main page
            if(firebase.auth().currentUser){
                const currentUser = firebase.auth().currentUser;
                const uid = currentUser.uid;
                const email = currentUser.email;
                const user = {
                    uid,
                    email,
                    updatedAt: moment().format('LLLL'),
                    createdAt: moment().format('LLLL')
                };
                // add this user to our database
                databaseRef.child(`users/${uid}`).update(user);
                // store user to state (dispatches ADD_USER_DATA action - this should update component!)
                dispatch(storeUserDataToState(user));
                // route user to main logged in view
                dispatch(startLoginForAuthorizedUser(uid));
            }
        }, (error) => {
            console.log("actions.jsx: Problem verifying email: ", error);
        });
    }
};

export const storeUserDataToState = (data) => {
    return{
        type: 'ADD_USER_DATA',
        data
    };
};

Reducers.jsx

export const userReducer = (state = initialUserState, action) => {
    switch(action.type){
        case 'ADD_USER_DATA':
            // Add new user data to state
            return {
                ...state,
                ...action.data
            };
        case 'RESET_USER_DATA':
            return initialUserState;
        default:
            return state;
    }
};

此时,当我检查devTools时,似乎状态更新正常。如您所见,状态未发生变化 - 我正在返回一个新对象,并使用spread运算符填充前两个数据。但是,我的MainView组件不会使用更新的状态数据重新呈现:

MainView.jsx

import React from 'react';
import * as Redux from 'react-redux';
import * as actions from 'actions';

export const MainView = React.createClass({

    render(){

        const { user } = this.props;

        // user object is still default even after state updated in devTools.

        return(
            <div>
                // None of this shows up
                { user.uid &&
                    <div>
                        <h3>Data:</h3>
                        <p><b>User ID: </b>{ user.uid }</p>
                        <p><b>Email: </b>{ user.email }</p>
                        <p><b>Updated At: </b>{ user.updatedAt }</p>
                    </div>
                }
            </div>
        );
    }
});

export default Redux.connect(state => {
    // State is still initialState here. 
    // state.user is the correct name of the reducer.
    return {
        user: state.user
    };
})(MainView);

Routes.jsx

import React from 'react';
import { Route, Router, IndexRoute, browserHistory } from 'react-router';
import * as actions from 'actions';

// Components
import App from 'App';
import Landing from 'landing/Landing.jsx';
import Verify from 'landing/Verify.jsx';
import MainView from 'mainview/MainView.jsx';

import firebase from 'app/firebase';

const store = require('store').configure();

const requireLogin = (nextState, replace, next) => {
    const currentUser = firebase.auth().currentUser;
    if(!currentUser){
        replace('/');
    }
    next();
};

const redirectIfLoggedIn = (nextState, replace, next) => {
    const currentUser = firebase.auth().currentUser;
    currentUser ? replace('mainview') : console.log('no currentUser.');
    next();
};

const verifyUserEmail = (nextState, replace, next) => {
    const { mode, oobCode } = nextState.location.query;
    console.log("router: mode & oobCode from verifyUserEmail: ", mode, oobCode);
        if(mode == 'verifyEmail' && oobCode){
            store.dispatch(actions.verifyEmailWithCode(oobCode));
        } else {
            replace('/');
        }
    next();
}

export default (
    <Router history={ browserHistory }>
        <Route path="/" component={ App }>
            <IndexRoute component={ Landing } onEnter={ redirectIfLoggedIn } />
            <Route path="verify" component={ Verify } onEnter={ verifyUserEmail } />
            <Route path="mainview" component = { MainView } onEnter = { requireLogin } />
        </Route>
    </Router>
);

Store.jsx

import * as redux from 'redux';
import thunk from 'redux-thunk';
import { reducer as form } from 'redux-form';
import { browserHistory } from 'react-router';
import { authReducer, imgUrlReducer, uiStateReducer, errorsReducer, userReducer } from 'reducers';

export var configure = (initialState = {}) => {
    var reducer = redux.combineReducers({
        form,
        auth: authReducer,
        imgUrl: imgUrlReducer,
        uiState: uiStateReducer,
        errors: errorsReducer,
        user: userReducer
    });

    // Add middleware here --
    var store = redux.createStore(reducer, initialState, redux.compose(
        redux.applyMiddleware(thunk),
        window.devToolsExtension ? window.devToolsExtension() : f => f
    ));

    return store;
};

关于我在这里做错了什么的想法?我在SO上检查了与此相关的每个问题,然后用谷歌搜索死亡。我很傻。

0 个答案:

没有答案