Selector returns 来自 redux 状态的空数组,即使该数组有值

Selector returns empty array from the redux state, even though the array has values

我有以下规范化的 redux 状态:

rootReducer: {
  blocks: {
    "key1": {
      id: "key1",
      beverages: [], // Array of objects
    }
  }
}

并且我正在尝试 select 使用此 select 或:

为 ID 为 "key1" 的饮料 beverages 的值
export const getBlockBeverages = (state, blockId) => {
    console.log("selector", state.blocks[blockId].beverages);
    return state.blocks[blockId].beverages;
};

每当我向 beverages 数组中添加新饮料时,selector 都会被调用两次,第一次使用空数组,第二次使用正确的值:

初始状态

selector []
selector []

添加新饮料:

selector []
selector [{/*beverage1*/}]

// Adding another beverage
selector []
selector [{/*beverage1*/}, {/*beverage2*/}]

我真的很感激 help/explanation 为什么 selector 被调用并且块实例的 beverages 值是一个空数组。

下面是我正在使用的 reducer 的代码 - 我看不出我可以在哪里改变原始状态,我从一开始就使用了 Immer 的产品,但问题仍然存在。然后我尝试使用 lodash.clonedeep 来确保我 return 一个新状态,但是 selector 仍然记录那个空数组。

const blockReducer = (state = { id: "", beverages: [] }, action) => {
    if (action.type === ADD_BEVERAGE_TO_BLOCK) {
        const { beverageId } = action.payload;
        const newBeverage = { id: uuid4(), beverageId };
        return produce(state, (draft) => {
            draft.beverages.push(newBeverage);
        });
    }
    return state;
};


const blocks = (state = {}, action) => {
    const key = action.payload.key;
    if (key && (state[key] || action.type === CREATE_BLOCK)) {
        const instanceState = blockReducer(state[key], action);
        return produce(state, (draft: any) => {
            draft[key] = instanceState;
        });
    }
    return state;
};

知道为什么在添加新饮料时使用 select 或 return 的空数组而不是长度为 0、1、2 等的数组吗?我一无所知,将不胜感激。

问题出在我一直错误使用的另一个选择器中。

export const makeGetBlockBeveragesLength = () => createSelector(
    (state, blockId) => getBlockBeverages(state, blockId),
    (blockBeverages) => blockBeverages.length,
);

我使用 createMapStateToProps 代替 mapStateToProps:

const createMapStateToProps = (state, { blockId }) => () => {
    const getBlockBeveragesLength = makeGetBlockBeveragesLength();
    return {
        length: getBlockBeveragesLength(state, blockId),
    };
};

export const Component = connect(createMapStateToProps)(MyComponent);

其中一个日志中记录的空数组指的是较旧的状态(在本例中为初始状态)。

我将代码修改为这个并且它有效:

export const getBlockBeveragesLength = createSelector(
    (state, blockId) => getBlockBeverages(state, blockId),
    (blockBeverages) => blockBeverages.length,
);
const mapStateToProps = (state, { blockId }) => ({
    length: getBlockBeveragesLength(state, blockId),
});

export const Component = connect(mapStateToProps)(MyComponent);