React / Redux / Reselect - 使用同步或异步选择器将状态映射到道具?
React / Redux / Reselect - is mapped state to props using selectors synchronous or asynchronous?
在我们的项目中,我们使用 react-redux
与 reselect
和 redux-saga
在商店中,我有一个 selectedStageId
以及一个 stages
数组和一个根据 ID 找到并 returns 正确阶段的记忆选择器。
此选择器作为 this.props.selectedStage
映射到我的组件道具之一,并且在我的一个 onClick 处理程序中,我发送一个操作以将 selectedStageId
更新为新选择的 ID UI 项,然后尝试将新的 selectedStage
传递给编辑方法...
然而,即使我添加了断点并验证我的 reducer 和选择器都被新的 id 调用,新的 selectedStage
值并没有在我的组件的 props 上同步更新......相反this.props.selectedStage
仍然引用以前的值...
示例:
onItemSelect = (stageId: number): void => {
// updateSelectedStageId() is a mapped dispatch method that updates
// selectedStageId in the store
this.props.updateSelectedStageId(stageId);
// I have debugged the above dispatched action and verified that
// both the reducer and selector are being called with the new
// stageId, and the selector is executing and returning the correct
// new stage object before the next line is processed...
this.editStage(this.props.selectedStage;); // <-- wrong value
// this.props.selectedStage is the mapped memoized selector that
// returns the target stage based on the selectedStageId, but
// here it still references the previous value, not the new one
}
我读过 redux 通常是同步的,但是 redux-saga 可能会以某种方式使它异步......但是,由于我已经验证了 reducer 和 selector 都是同步调用的,所以似乎问题出在其他地方,可能是在 connect 实际将映射状态更新为 props 时...
任何人都可以提供一些关于如何以正确的方式完成此任务的见解吗?
谢谢!
乔什
更新
这是我的减速器和选择器的相关位...
reducer.ts
import produce from 'immer';
const initialState = {
selectedStageId: -1,
stages: []
}
export const appReducer = (state = initialState, action) => {
return produce(state, (draftState) => {
switch (action.type) {
case ActionType.UpdateSelectedStageId
draftState.selectedStageId = action.id;
break;
}
});
}
selectors.ts
import { createSelector } from 'reselect';
const _getSelectedStage = (stages, id) => {
return stages.find((s) => s.id === id);
};
export const selectedStage = createSelector(
[getStages, getSelectedStageId],
_getSelectedStage
);
我遇到了同样的问题(实际上几乎一样)today。
每个状态的改变(redux 与否)都是异步的。您实际上不能相信该值会被更新。
Triggering a synchronous action doesn't mean it's synchronous within the current rendering phase. So your app dispatch the action, finishes the rendering, then the new redux state triggers a re-render.
dispatch({type: CHANGE_VALUE, value : newValue})
console.log(value) //oldValue
状态获取是同步更新的,但 React 只会在下一次渲染时意识到该变化。
因此,只需使用您正在调度操作的值:
onItemSelect = (stageId: number): void => {
this.props.updateSelectedStageId(stageId);
this.editStage(stageId)
}
在我们的项目中,我们使用 react-redux
与 reselect
和 redux-saga
在商店中,我有一个 selectedStageId
以及一个 stages
数组和一个根据 ID 找到并 returns 正确阶段的记忆选择器。
此选择器作为 this.props.selectedStage
映射到我的组件道具之一,并且在我的一个 onClick 处理程序中,我发送一个操作以将 selectedStageId
更新为新选择的 ID UI 项,然后尝试将新的 selectedStage
传递给编辑方法...
然而,即使我添加了断点并验证我的 reducer 和选择器都被新的 id 调用,新的 selectedStage
值并没有在我的组件的 props 上同步更新......相反this.props.selectedStage
仍然引用以前的值...
示例:
onItemSelect = (stageId: number): void => {
// updateSelectedStageId() is a mapped dispatch method that updates
// selectedStageId in the store
this.props.updateSelectedStageId(stageId);
// I have debugged the above dispatched action and verified that
// both the reducer and selector are being called with the new
// stageId, and the selector is executing and returning the correct
// new stage object before the next line is processed...
this.editStage(this.props.selectedStage;); // <-- wrong value
// this.props.selectedStage is the mapped memoized selector that
// returns the target stage based on the selectedStageId, but
// here it still references the previous value, not the new one
}
我读过 redux 通常是同步的,但是 redux-saga 可能会以某种方式使它异步......但是,由于我已经验证了 reducer 和 selector 都是同步调用的,所以似乎问题出在其他地方,可能是在 connect 实际将映射状态更新为 props 时...
任何人都可以提供一些关于如何以正确的方式完成此任务的见解吗?
谢谢!
乔什
更新
这是我的减速器和选择器的相关位...
reducer.ts
import produce from 'immer';
const initialState = {
selectedStageId: -1,
stages: []
}
export const appReducer = (state = initialState, action) => {
return produce(state, (draftState) => {
switch (action.type) {
case ActionType.UpdateSelectedStageId
draftState.selectedStageId = action.id;
break;
}
});
}
selectors.ts
import { createSelector } from 'reselect';
const _getSelectedStage = (stages, id) => {
return stages.find((s) => s.id === id);
};
export const selectedStage = createSelector(
[getStages, getSelectedStageId],
_getSelectedStage
);
我遇到了同样的问题(实际上几乎一样)today。
每个状态的改变(redux 与否)都是异步的。您实际上不能相信该值会被更新。
Triggering a synchronous action doesn't mean it's synchronous within the current rendering phase. So your app dispatch the action, finishes the rendering, then the new redux state triggers a re-render.
dispatch({type: CHANGE_VALUE, value : newValue})
console.log(value) //oldValue
状态获取是同步更新的,但 React 只会在下一次渲染时意识到该变化。
因此,只需使用您正在调度操作的值:
onItemSelect = (stageId: number): void => {
this.props.updateSelectedStageId(stageId);
this.editStage(stageId)
}