reactjs - 使用 combineReducers 时调度动作不会触发渲染
问题描述
当我不使用 combineReducers 时:
const store = createStore<StoreState,any,any,any>(pointReducer, {
points: 1,
languageName: 'Points',
});
function tick() {
store.dispatch(gameTick());
requestAnimationFrame(tick)
}
tick();
一切正常,我的组件更新。但是,当我这样做时:
const reducers = combineReducers({pointReducer}) as any;
const store = createStore<StoreState,any,any,any>(reducers, {
points: 1,
languageName: 'Points',
});
商店确实更新了(通过控制台日志记录检查)但是组件没有呈现更改,我不知道为什么!
减速机:
export function pointReducer(state: StoreState, action: EnthusiasmAction): StoreState {
switch (action.type) {
case INCREMENT_ENTHUSIASM:
return { ...state, points: state.points + 1 };
case DECREMENT_ENTHUSIASM:
return { ...state, points: Math.max(1, state.points - 1) };
case GAME_TICK:
return { ...state, points: state.points + 1 };
default:
return state;
}
}
和组件:
export interface Props {
name: string;
points: number;
onIncrement: () => void;
onDecrement: () => void;
}
class Points extends React.Component<Props, object> {
constructor(props: Props) {
super(props);
}
render() {
const { name, points, onIncrement, onDecrement } = this.props;
return (
<div className="hello">
<div className="greeting">
Hello {name + points}
</div>
<button onClick={onDecrement}>-</button>
<button onClick={onIncrement}>+</button>
</div>
);
}
}
export default Points;
容器:
export function mapStateToProps({ points, languageName }: StoreState) {
return {
points: points,
name: languageName,
}
}
export function mapDispatchToProps(dispatch: Dispatch<actions.EnthusiasmAction>) {
return {
onIncrement: () => dispatch(actions.incrementEnthusiasm()),
onDecrement: () => dispatch(actions.decrementEnthusiasm())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Points);
存储状态:
export interface StoreState {
languageName: string;
points: number;
food: number;
wood: number;
}
进行建议的更改时(更改减速器和组合减速器,我收到一个新错误:
我的减速器现在看起来像:
export function pointReducer(state: 1, action: EnthusiasmAction) {
switch (action.type) {
case INCREMENT_ENTHUSIASM:
return state + 1;
case DECREMENT_ENTHUSIASM:
return Math.max(1, state - 1);
case GAME_TICK:
return state + 1;
default:
return state;
}
}
解决方案
问题可能在于您如何使用combineReducers
,而不是您如何编写mapState
函数。
我猜你的mapState
函数看起来像:
const mapState = (state) => {
return {
points : state.points
}
}
当您单独使用时,这可以正常工作pointsReducer
,因为您的状态具有state.points
.
然而,当你使用combineReducers
你现在的方式时,你给自己制造了两个问题:
- 您正在命名状态字段
state.pointsReducer
,而不是state.points
- 您
pointsReducer
进一步将数据嵌套为points
因此,您想要的实际数据位于state.pointsReducer.points
,而组件期望它位于state.points
。
要解决此问题,您应该更改调用方式combineReducers
,并将pointsReducer
定义更改为仅跟踪数据而不进行嵌套:
export function pointReducer(state: 1, action: EnthusiasmAction): StoreState {
switch (action.type) {
case INCREMENT_ENTHUSIASM:
return state + 1
case DECREMENT_ENTHUSIASM:
return Math.max(1, state - 1);
case GAME_TICK:
return state.points + 1;
default:
return state;
}
}
// later
const rootReducer = combineReducers({
points : pointsReducer,
languageName : languageNameReducer,
});
有关更多详细信息,请参阅有关“使用”的Redux 文档页面combineReducers
推荐阅读
- android - 改造库不支持所有设备版本
- php - 如何计算表中的值并返回true,仅当使用php mysql找到该值5次时
- python - 用不同的开始和结束时间在python中分割wav文件
- azure - MS Azure“云中的主机”复选框下的下拉菜单没有“应用服务”值
- sql - 在 SQL 中查询列中的 JSON 并创建视图
- java - 来自 Java Web 应用程序的 FileNotFoundException
- java - 如何正确关闭 Spring AMQP 连接
- php - 如何将两个 foreach 放入一个 foreach 循环?
- python - 连接两个不同长度的列表中的元素
- html - 具有块重叠设计问题的图像