Redux 状态不会随着动作调度而更新
Posted
技术标签:
【中文标题】Redux 状态不会随着动作调度而更新【英文标题】:Redux state doesn't update with action dispatch 【发布时间】:2017-05-19 10:19:17 【问题描述】:我已经浏览了我可以找到的所有文档和示例项目,用于使用 redux 和 react-router 构建一个 react 应用程序,但我似乎无法弄清楚如何让我的 redux 状态在我更新时调度动作。正如您在此屏幕截图中看到的,动作正在正确调度,但我的 store/nextState 没有更新。
动作:
export function updateUsername(username)
return type: types.UPDATE_USERNAME, username ;
REDUCER(编辑:我已经尝试了这两种变体):
/* first variation */
const username = (
state = '',
action,
) =>
switch (action.type)
case types.UPDATE_USERNAME:
return Object.assign(, state,
username: action.username,
);
default:
return state;
;
/* second variation */
const username = (
state = '',
action,
) =>
switch (action.type)
case types.UPDATE_USERNAME:
return action.username;
default:
return state;
;
减速机组合:
const user = combineReducers(
isAuthenticated,
token,
password,
username,
);
export default user;
REDUCERS/INDEX.JS:
const rootReducer = combineReducers(
isFetching,
open,
search,
user,
routing: routerReducer,
);
export default rootReducer;
商店配置:
import React from 'react';
import createStore, compose, applyMiddleware from 'redux';
import createLogger from 'redux-logger';
import thunkMiddleware from 'redux-thunk';
import routerMiddleware from 'react-router-redux';
import rootReducer from '../reducers';
import * as actions from '../actions';
function configureStore(history, initialState)
const loggerMiddleware = createLogger();
const enhancer = window.__REDUX_DEVTOOLS_EXTENSION__ &&
window.__REDUX_DEVTOOLS_EXTENSION__();
const store = createStore(
rootReducer,
initialState,
compose(
applyMiddleware(
thunkMiddleware,
loggerMiddleware,
routerMiddleware(history),
),
enhancer,
),
);
if (module.hot)
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers', () =>
const nextReducer = rootReducer;
store.replaceReducer(nextReducer);
);
return store;
export default configureStore;
商店创建:
const initialState = ;
const store = configureStore(browserHistory, initialState);
const history = syncHistoryWithStore(browserHistory, store);
const routes = createRoutes(store);
render(
<Provider store=store>
<Router history=history routes=routes />
</Provider>,
document.getElementById('root'),
);
最后是组件:
import React, Component, PropTypes from 'react';
import connect from 'react-redux';
import bindActionCreators from 'redux';
import TextField from 'material-ui/TextField';
import validator from 'validator';
import className from 'classnames';
import Link from 'react-router';
import * as AuthActions from '../../actions/AuthActions';
class LoginForm extends Component
constructor(props)
super(props);
this.handleUsernameChange = this.handleUsernameChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
handleUsernameChange(e)
this.props.actions.updateUsername(validator.escape(e.target.value.trim()));
handlePasswordChange(e)
this.props.actions.updatePassword(validator.escape(e.target.value.trim()));
handleSubmit(e, getState)
e.prevent.default();
const user = username: this.props.user.username, password: this.props.user.password ;
console.log(user);
this.props.actions.loginUser(user);
render()
return (
<form autoComplete="off" onSubmit=this.handleSubmit className='login-form'>
<TextField
type="username"
autoFocus="true"
floatingLabelText="Username"
floatingLabelFixed=true
autoComplete="off"
onChange=this.handleUsernameChange
/>
<br/>
<TextField
type="password"
autoFocus="true"
floatingLabelText="Password"
floatingLabelFixed=true
autoComplete="off"
onChange=this.handlePasswordChange
/>
</form>
);
function mapStateToProps(state)
return
user: state.user,
;
function mapDispatchToProps(dispatch)
return
actions: bindActionCreators(AuthActions, dispatch),
;
export default connect(
mapStateToProps,
mapDispatchToProps,
)(LoginForm);
我已经坚持了一周了,因此非常感谢您提供的任何帮助!谢谢!
【问题讨论】:
这些代码正确吗?您在日志中显示 UPDATE_USERNAME...但提供的操作代码是 UPDATE_PASSWORD 好收获。只需复制/粘贴错误的操作。已编辑! 你能提供一个 repo 以便我可以克隆和运行吗? @LucasKatayama 我会整理一个你可以在早上克隆的 repo。在那之前,我通过为我的每个 reducer 声明“return state = action.username”找到了一种解决方法。不理想,但它正在工作。 【参考方案1】:我没有运行你的代码,所以我不能随便说如果这能解决它,但是你的用户名reducer返回一个带有username
属性的对象,而它应该返回action.username
字符串.
const username = (state = '', action) =>
switch (action.type)
case types.UPDATE_USERNAME:
return action.username
default:
return state;
;
另外,您是否确认您的types
声明中没有错字?我看到在你的减速器中你引用了types.UPDATE_USERNAME
,但是在你的动作创建器中你使用字符串UPDATE_USERNAME
来设置类型。
【讨论】:
不幸的是,我已经为reducer 尝试了这种格式,以及许多其他变体。似乎都没有工作。至于类型声明,我在 reducer 文件中导入了“* as types”。我现在试试切换。 您是否将console.log
放入您的username
减速器以确保它被调用? (或者只是在开发工具中添加了一个断点)
是的,它正在发射。当我发送登录操作时,我的后端授权服务也收到了 200,但同样的问题是 nextState 没有更新。
好吧,我还是什么都没看到。您是否尝试过使用调试器单步执行 combineReducers
返回的减速器? github.com/reactjs/redux/blob/v3.6.0/src/… 这应该会验证所有 reducer 函数的返回值。
你应该保持状态可变。设置为“state=something”可以改变应用程序的整个状态。相反,它应该从减速器返回状态为“return Object.assign(, state, action);”以上是关于Redux 状态不会随着动作调度而更新的主要内容,如果未能解决你的问题,请参考以下文章
在通过动作调度进行状态更新后,在 React 中使用 Redux 执行函数?