Ngrx-存储更改后选择器未发出新值

时间:2018-08-14 15:39:12

标签: angular observable ngrx ngrx-store

我的状态看起来像这样:

export interface State {
  modules: Module[];
}

Module接口类似于:

export interface Module {
  name: string;
  structure: {
    moduleID: string;
    icon: string;
    ...
  };
  data: [{id: string; value: string; }];
}

模块中的数据连接到输入字段和组合框。当用户在输入字段中更改某些内容时,化简器将分派动作,并使用给定数据对象的新数据值来更新存储。我已经验证了更改在商店中发生。

Reducer正在执行以下操作:( getModules()仅返回具有该名称的模块,而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;
});

订阅选择器后,我得到了其中的当前值,但是无论缩减器更新该特定数据对象多少次,它都不会再次触发。有什么想法我想念的吗?谢谢。

1 个答案:

答案 0 :(得分:4)

该问题可能是因为更新moduleToChange上的属性时,您的changeElementData函数未创建新对象。

我猜你有这样的东西:

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会假定其未更改。

相关问题