我正在尝试使用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上检查了与此相关的每个问题,然后用谷歌搜索死亡。我很傻。