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);
我有以下规范化的 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);