ngrx - значения по умолчанию перезаписываются через оператор распространения? - PullRequest
0 голосов
/ 30 апреля 2018

Я работаю над селектором ngrx, который преобразует раздел дерева состояний в модель представления. В качестве простого примера, в моем дереве состояний у меня есть массив manager. Таким образом, у меня есть следующая настройка для моего дерева состояний и просмотр модели-

export interface Manager {
    id: string,
    name: string
}

export interface AppState {
    managers: Manager[]
}

export interface ManagersVM {
    byId: {[key: string]: Manager},
    allIds: string[]
}

export const defaultManagersVM: ManagersVM {
    byId: {},
    allIds: []
};

Тогда в моем селекторе у меня есть:

export const selectManagersVM = createSelector(selectManagers, (data) => {
    let mgrsVM: ManagersVM = { ...defaultManagersVM };
    for(let mgr of data.managers) {
        mgrsVM.byId[mgr.id] = mgr;
        mgrsVM.allIds.push(mgr.id);
    }
})

Проблема, с которой я сталкиваюсь, заключается в том, что строка:

let mgrsVM: ManagersVM = { ...defaultManagersVM };

, похоже, не делает копию свойств defaultManagersVMs. (console.log из defaultManagersVM после запуска селектора показывает, что теперь у него есть непустые byId и allIds). У меня сложилось впечатление, что оператор распространения внутри вновь определенного объекта создаст копию, но это неправильно. Как я могу гарантировать, что defaultManagersVM не будет видоизменяться в моем селекторе.

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вот рекурсивный deepClone метод, который я нашел где-то, который, кажется, делает работу

export function deepClone(state) {

  if (Array.isArray(state)) {
    const newState = [];
    for (let index = 0; index < state.length; index++) {
      const element = state[index];
      newState[index] = deepClone(element);
    }
    return newState;
  }
  if (typeof state === 'object') {
    const newState = {...state};
    Object.keys(newState).forEach(key => {
      if (newState.hasOwnProperty(key)) {
        const val = newState[key];
        newState[key] = deepClone(val);
      }
    });
    return newState;
  }

  return state;
}

Вы также можете применить deepFreeze ко всему, что не должно изменяться. Вы получаете ошибку, но, по крайней мере, она находится в точке мутации.

export function deepFreeze (o) {
  Object.freeze(o);

  Object.getOwnPropertyNames(o).forEach((prop) => {
    if (o.hasOwnProperty(prop)
    && o[prop] !== null
    && (typeof o[prop] === 'object')
    && !Object.isFrozen(o[prop])) {
      deepFreeze(o[prop]);
    }
  });

  return o;
}
0 голосов
/ 30 апреля 2018

Оператор распространения не делает глубокую копию вложенных объектов , JavaScript не имеет этой функции по умолчанию. Можно использовать внешнюю библиотеку (т. Е. Lodash , которая поддерживает глубокое клонирование).

В качестве альтернативы, вы можете написать свою собственную рекурсивную функцию глубокого клонирования, если вам требуется какая-то конкретная функциональность, которая не предусмотрена другими библиотеками.

...