我有以下规范化redux状态:
rootReducer: {
blocks: {
"key1": {
id: "key1",
beverages: [], // Array of objects
}
}
}
,我试图选择饮料beverages
的值与"key1"
的id使用此选择器:
export const getBlockBeverages = (state, blockId) => {
console.log("selector", state.blocks[blockId].beverages);
return state.blocks[blockId].beverages;
};
每当我向beverages
数组中添加新饮料时,选择器被调用两次,第一次使用空数组,第二次使用适当的值:
selector []
selector []
添加新饮料:
selector []
selector [{/*beverage1*/}]
// Adding another beverage
selector []
selector [{/*beverage1*/}, {/*beverage2*/}]
我真的很感激任何帮助/解释为什么选择器被调用和beverages
值块实例是一个空数组。
下面是我正在使用的reducer的代码-我不知道我可以在哪里改变原始状态,我从一开始就使用Immer的产品,问题仍然存在。然后我尝试使用lodash。clonedeep,以确保我返回一个新的状态,但选择器仍然记录空数组。
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;
};
任何想法为什么选择器返回空数组,而不是长度0,1,2等数组,因为我添加新的饮料?我不懂,如果你能帮我,我将不胜感激。
问题是在一个不同的选择器,我一直在错误的方式使用。
export const makeGetBlockBeveragesLength = () => createSelector(
(state, blockId) => getBlockBeverages(state, blockId),
(blockBeverages) => blockBeverages.length,
);
而不是mapStateToProps,我使用createMapStateToProps:
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);