Ngrx - 选择器在存储更改后不发出新值
Ngrx - selector is not emitting new value after store change
我的状态看起来像这样:
export interface State {
modules: Module[];
}
模块接口类似于:
export interface Module {
name: string;
structure: {
moduleID: string;
icon: string;
...
};
data: [{id: string; value: string; }];
}
模块中的数据连接到输入字段和组合框。当用户更改输入字段中的某些内容时,将调度一个操作,并且 reducer 会使用给定数据对象的新数据值更新存储。我已经确认更改发生在商店中。
Reducer 正在执行以下操作:(getModules() 只是 returns 具有该名称的模块,而 changeElementData() 找到要更改的元素并在其上执行 data.value = value)
case fromTitelActions.SET_DATA: {
const stateCopy = {...state};
const moduleToChange = getModule(action.payload.nameOfModule, stateCopy.modules);
action.payload.data.forEach(data => changeElementData(moduleToChange, data.Id, data.value));
return stateCopy;
}
我正在尝试订阅特定数据值并检测更改。我的选择器如下所示:
export const getDataElementValue = (moduleName, elementId) => createSelector(getModules,
modules => {
const module = modules.find(m => m.name === moduleName);
const data = module.data.find( d => d.id === elementId);
return data.value;
});
订阅选择器后,我得到了其中的当前值,但它再也不会触发,无论 reducer 更新该特定数据对象多少次。有什么想法我想念的吗?谢谢
问题可能是因为您的 changeElementData 函数在更新 moduleToChange 上的 属性 时没有创建新对象。
我猜你有这样的东西:
function changeElementData(moduleToChange, id, value) {
moduleToChange.elements.forEach((el) => {
if (el.id == id) el.value = value;
});
}
你需要这样的东西:
case fromTitelActions.SET_DATA: {
const stateCopy = {...state};
stateCopy.modules = stateCopy.modules.map((moduleToChange) => {
if (module.name != action.payload.nameOfModule) return moduleToChange;
else return action.payload.data.map(data => changeElementData(moduleToChange, data.Id, data.value));
});
return stateCopy;
}
function changeElementData(moduleToChange, id, value) {
let found: boolean = false;
let newModule = module;
if (moduleToChange.elements.find((el) => el.id == id)) {
newModule = {
...moduleToChange,
elements: moduleToChange.elements.map((el) => {
if (el.id == id) return { ...el, value: value };
else return el;
})
}
}
return newModule;
}
在状态上更新对象的 属性 时,您必须始终创建一个新的包含对象,因为 NGRX 使用简单的对象相等性来确定是否发生了某些变化并触发相关的可观察对象。如果您更新一个对象的 属性,该对象本身仍然具有与其先前版本相同的引用,因此 NGRX 将假定它没有变化。
我的状态看起来像这样:
export interface State {
modules: Module[];
}
模块接口类似于:
export interface Module {
name: string;
structure: {
moduleID: string;
icon: string;
...
};
data: [{id: string; value: string; }];
}
模块中的数据连接到输入字段和组合框。当用户更改输入字段中的某些内容时,将调度一个操作,并且 reducer 会使用给定数据对象的新数据值更新存储。我已经确认更改发生在商店中。
Reducer 正在执行以下操作:(getModules() 只是 returns 具有该名称的模块,而 changeElementData() 找到要更改的元素并在其上执行 data.value = value)
case fromTitelActions.SET_DATA: {
const stateCopy = {...state};
const moduleToChange = getModule(action.payload.nameOfModule, stateCopy.modules);
action.payload.data.forEach(data => changeElementData(moduleToChange, data.Id, data.value));
return stateCopy;
}
我正在尝试订阅特定数据值并检测更改。我的选择器如下所示:
export const getDataElementValue = (moduleName, elementId) => createSelector(getModules,
modules => {
const module = modules.find(m => m.name === moduleName);
const data = module.data.find( d => d.id === elementId);
return data.value;
});
订阅选择器后,我得到了其中的当前值,但它再也不会触发,无论 reducer 更新该特定数据对象多少次。有什么想法我想念的吗?谢谢
问题可能是因为您的 changeElementData 函数在更新 moduleToChange 上的 属性 时没有创建新对象。
我猜你有这样的东西:
function changeElementData(moduleToChange, id, value) {
moduleToChange.elements.forEach((el) => {
if (el.id == id) el.value = value;
});
}
你需要这样的东西:
case fromTitelActions.SET_DATA: {
const stateCopy = {...state};
stateCopy.modules = stateCopy.modules.map((moduleToChange) => {
if (module.name != action.payload.nameOfModule) return moduleToChange;
else return action.payload.data.map(data => changeElementData(moduleToChange, data.Id, data.value));
});
return stateCopy;
}
function changeElementData(moduleToChange, id, value) {
let found: boolean = false;
let newModule = module;
if (moduleToChange.elements.find((el) => el.id == id)) {
newModule = {
...moduleToChange,
elements: moduleToChange.elements.map((el) => {
if (el.id == id) return { ...el, value: value };
else return el;
})
}
}
return newModule;
}
在状态上更新对象的 属性 时,您必须始终创建一个新的包含对象,因为 NGRX 使用简单的对象相等性来确定是否发生了某些变化并触发相关的可观察对象。如果您更新一个对象的 属性,该对象本身仍然具有与其先前版本相同的引用,因此 NGRX 将假定它没有变化。