发生调度,但商店仅部分更新
Dispatches occur, but store is only partially updated
我正在尝试为我的登录流程更新我的用户状态。用户是 rootReducer 的一部分。 Session也是,不过那个state的reducer是属于redux-react-session库的。
我的登录流程是:用户访问页面,输入用户名和密码。用户按下登录表单按钮。在提交时,会话调用服务器并让用户登录。在登录过程中,运行用户状态的调度。
但是运行之后,用户态还是原来的样子。显然登录成功了。所以会话状态会填充新数据,而用户状态不会。整个日志表明调用了 userReducer,并且它 returns 的状态符合预期。是否有一些特殊的方法可以将 userReducer 连接到商店或更新它?以下代码失败。
我找到的文档没有显示是否有必要区别对待 rootReducer 存储和非组合存储。此外,登录流程依赖于相同的函数来分派这两个操作,因此问题一定出在 userReducer 或操作中。
编辑:提供的代码在遇到 userReducer 时会落入默认情况。我通过将默认大小写设置为提供不同的电子邮件值来确认这一点。为什么 userReducer 不接受操作类型 UserActions#userAdd returns?什么时候调用 userReducer?
Edit2:放置在 userReducer 中的调试器显示分派操作最初确实到达了 'ADD_USER' 和 returns 正确的对象,但它在之后立即分派了几次,并以某种方式重置了介于两者之间的用户状态加载不同的页面。这是正常行为吗?
//rootReducer.js
const reducers = {
user: userReducer,
session: sessionReducer
};
const rootReducer = combineReducers(reducers);
//userReducer.js
function userReducer(state = { email: '', projects: [] }, action) {
switch (action.type) {
case 'ADD_USER':
return Object.assign({}, state, action.user);
case 'LOGOUT_USER':
return {email: '', projects: [] };
case 'EDIT_USER':
return { email: '', projects: [] };
case 'DELETE_USER':
return { email: '', projects: [] };
default:
return state;
}
}
export default userReducer;
//LoginContainer.js
//this component calls the failing dispatch
//dispatch is default provided dispatch from connect function
import { connect } from 'react-redux';
import * as sessionActions from '../actions/SessionActions';
import * as userActions from '../actions/UserActions';
...
onSubmit = (e, history) => {
e.preventDefault();
this.props.dispatch(sessionActions.login(this.state, history, this.props.dispatch, userActions.addUser))
//addUser({email: this.state.email, projects: []});
}
...
export default connect(null)(LoginContainer);
//SessionActions.js
//failing code lives here:
//dispatch(addUser(json)); seems to fail somehow
//even though flow is basically the same as session
export const login = (state, history, dispatch, addUser) => {
return () => {
return sessionApi.login(state).then(response => response.json()).then(json => {
sessionService.saveSession({ json })
.then(() => {
sessionService.saveUser(json)
.then(() => {
if (json.email) {
console.log(state);
console.log(json);
dispatch(addUser(json));
localStorage.setItem("loggedIn", true);
localStorage.setItem("user", JSON.stringify(json.email));
history.push('/');
//history.go(0);
}
}).catch(err => console.error(err));
}).catch(err => console.error(err));
});
};
};
//UserActions.js
export const addUser = (user) => {
console.log(user);
return {type: 'ADD_USER', user }
}
我明白了。该项目需要 redux-persist 以便状态数据从一页重新水合到下一页。会话状态对此功能有自己的处理。
combineReducers 和 redux-react-session 和 redux-thunk 的实现代码如下。我仍在努力完善合并级别。
$ npm install redux-persist
//configureStore.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { sessionService } from 'redux-react-session';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import rootReducer from './rootReducer';
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export let store = createStore(persistedReducer, applyMiddleware(thunk));
sessionService.initSessionService(store);
export let persistor = persistStore(store);
我正在尝试为我的登录流程更新我的用户状态。用户是 rootReducer 的一部分。 Session也是,不过那个state的reducer是属于redux-react-session库的。
我的登录流程是:用户访问页面,输入用户名和密码。用户按下登录表单按钮。在提交时,会话调用服务器并让用户登录。在登录过程中,运行用户状态的调度。
但是运行之后,用户态还是原来的样子。显然登录成功了。所以会话状态会填充新数据,而用户状态不会。整个日志表明调用了 userReducer,并且它 returns 的状态符合预期。是否有一些特殊的方法可以将 userReducer 连接到商店或更新它?以下代码失败。
我找到的文档没有显示是否有必要区别对待 rootReducer 存储和非组合存储。此外,登录流程依赖于相同的函数来分派这两个操作,因此问题一定出在 userReducer 或操作中。
编辑:提供的代码在遇到 userReducer 时会落入默认情况。我通过将默认大小写设置为提供不同的电子邮件值来确认这一点。为什么 userReducer 不接受操作类型 UserActions#userAdd returns?什么时候调用 userReducer?
Edit2:放置在 userReducer 中的调试器显示分派操作最初确实到达了 'ADD_USER' 和 returns 正确的对象,但它在之后立即分派了几次,并以某种方式重置了介于两者之间的用户状态加载不同的页面。这是正常行为吗?
//rootReducer.js
const reducers = {
user: userReducer,
session: sessionReducer
};
const rootReducer = combineReducers(reducers);
//userReducer.js
function userReducer(state = { email: '', projects: [] }, action) {
switch (action.type) {
case 'ADD_USER':
return Object.assign({}, state, action.user);
case 'LOGOUT_USER':
return {email: '', projects: [] };
case 'EDIT_USER':
return { email: '', projects: [] };
case 'DELETE_USER':
return { email: '', projects: [] };
default:
return state;
}
}
export default userReducer;
//LoginContainer.js
//this component calls the failing dispatch
//dispatch is default provided dispatch from connect function
import { connect } from 'react-redux';
import * as sessionActions from '../actions/SessionActions';
import * as userActions from '../actions/UserActions';
...
onSubmit = (e, history) => {
e.preventDefault();
this.props.dispatch(sessionActions.login(this.state, history, this.props.dispatch, userActions.addUser))
//addUser({email: this.state.email, projects: []});
}
...
export default connect(null)(LoginContainer);
//SessionActions.js
//failing code lives here:
//dispatch(addUser(json)); seems to fail somehow
//even though flow is basically the same as session
export const login = (state, history, dispatch, addUser) => {
return () => {
return sessionApi.login(state).then(response => response.json()).then(json => {
sessionService.saveSession({ json })
.then(() => {
sessionService.saveUser(json)
.then(() => {
if (json.email) {
console.log(state);
console.log(json);
dispatch(addUser(json));
localStorage.setItem("loggedIn", true);
localStorage.setItem("user", JSON.stringify(json.email));
history.push('/');
//history.go(0);
}
}).catch(err => console.error(err));
}).catch(err => console.error(err));
});
};
};
//UserActions.js
export const addUser = (user) => {
console.log(user);
return {type: 'ADD_USER', user }
}
我明白了。该项目需要 redux-persist 以便状态数据从一页重新水合到下一页。会话状态对此功能有自己的处理。
combineReducers 和 redux-react-session 和 redux-thunk 的实现代码如下。我仍在努力完善合并级别。
$ npm install redux-persist
//configureStore.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { sessionService } from 'redux-react-session';
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
import rootReducer from './rootReducer';
const persistConfig = {
key: 'root',
storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export let store = createStore(persistedReducer, applyMiddleware(thunk));
sessionService.initSessionService(store);
export let persistor = persistStore(store);