React/Redux/Reselect-使用选择器同步还是异步将状态映射到道具? [英] React / Redux / Reselect - is mapped state to props using selectors synchronous or asynchronous?

查看:210
本文介绍了React/Redux/Reselect-使用选择器同步还是异步将状态映射到道具?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我们的项目中,我们将react-reduxreselectredux-saga

In our project we are using react-redux with reselect and redux-saga

在商店中,我有一个selectedStageId以及一个stages数组,以及一个记忆化的选择器,该选择器根据ID查找并返回正确的阶段.

In the store I have a selectedStageId along with an array of stages and a memoized selector that finds and returns the correct stage based on the id.

此选择器以this.props.selectedStage映射到我的一个组件道具,在我的一个onClick处理程序中,我调度了一个操作,将selectedStageId更新为新选择的UI项的ID,然后尝试将新的selectedStage传递给编辑方法...

This selector is mapped to one of my components props as this.props.selectedStage, and in one of my onClick handlers, I dispatch an action to update the selectedStageId to the id of the newly selected UI item, and then attempt to pass the new selectedStage to an edit method...

但是,即使我添加了断点并验证了我的reducer和selecters都已使用新的id进行了调用,新的selectedStage值仍未在组件的props上同步更新...而是this.props.selectedStage引用以前的值...

However, even though I have added breakpoints and verified that both my reducers and selectors are being called with the new id, the new selectedStage value is NOT being updated synchronously on my component's props... instead this.props.selectedStage still references the previous value...

示例:

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和选择器都是同步调用的,所以似乎这个问题位于其他地方,也许在connect实际将映射状态更新为props时...

I've read that redux is normally synchronous, but that redux-saga could somehow be making this asynchronous... However, since I've verified that both the reducer and selector are being called synchronously, it seems that the issue lies somewhere else, maybe in when connect actually updates mapped state to props...

任何人都可以提供一些有关如何以正确方式完成此目标的见解吗?

Can anyone provide some insight on how to accomplish this the right way?

谢谢!

乔什

更新

以下是我的减速器和选择器的相关信息...

Here are the related bits for my reducer and selector...

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
);

推荐答案

我遇到了相同的问题(实际上几乎相同)

I had the same problem (almost the same actually) today.

每个状态的更改(是否为Redux)都是异步的.您实际上不能相信该值将被更新.

Every state's change (redux or not) are asynchronous. You can't actually trust the value will be updated.

触发同步动作并不意味着它在当前渲染阶段是同步的.因此,您的应用将分派操作,完成渲染,然后新的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

状态get会同步更新,但是React只会在下一次渲染时才知道该更改.

The state get's updated synchronously, but React will only be aware of that change in the next render.

因此,只需使用您要分派操作的值即可:

So, just use the value you are dispatching the action:

onItemSelect = (stageId: number): void => {

  this.props.updateSelectedStageId(stageId);

  this.editStage(stageId)

}

这篇关于React/Redux/Reselect-使用选择器同步还是异步将状态映射到道具?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆