NGRX / REDUX: обновить значение в глубоком объекте по пути json - PullRequest
2 голосов
/ 14 июня 2019

У меня есть объект типа:

{
  categories: {
   Professional: {
    active: false,
    names: [
      {
        id: 1,
        name: "Golf",
        active: false
      },
      {
        id: 2,
        name: "Ultimate Frisbee",
        active: false
      }
  ] 
}}

, и я хочу обновить categories.Professional.active с true, в редуктор у меня есть:

return {
  ...state,
  categories: {
    ...state.categories,
    Professional: {
      ...state.categories.Professional,
      active: true
    }
  }
}

Теперь я хочу написатьфункция для распространения объекта и обновления одного свойства по пути json.Например,

return deepPatch(state, 'categories.Professional.active', true);

целью функции deepPatch является сборка во время выполнения этой структуры:

return Object.assign({}, obj, {
    categories: Object.assign({}, state.categories, {
      Professional: Object.assign({}, state.Professional, {
        active: true
      })
    })
});

Я пытался, но не знаю, как сделать рекурсивное распространение:

function deepPatch(obj: any, path: string; value: any){
   const arrayPath: string[] = path.split('.');
   const currObj = null;
   for (let i = 0, e = arrayPath.length; i < e; i++) {
       const currPath = arrayPath[i];
       currObj = obj[currPath];
       currObj = Object.assign({}, currObj, ???);
   }
   return currObj;
}

Ответы [ 2 ]

2 голосов
/ 14 июня 2019

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

function deepPatch(object, path, value) {
    var [key, rest] = path.match(/^[^.]+|[^.].*$/g);

    return { ...object, [key]: rest
        ? deepPatch(object[key], rest, value)
        : value
    };
}

var state = { categories: { Professional: { active: false, names: [{ id: 1, name: "Golf", active: false }, { id: 2, name: "Ultimate Frisbee", active: false }] } } },
    result = deepPatch(state, 'categories.Professional.active', true);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
2 голосов
/ 14 июня 2019
const deepSet = function (object, path, value) {
    if (typeof path === 'string') {
        path = path.split('.');
    }
    if (path.length > 1) {
        const e = path.shift();
        deepSet(object[e] = Object.prototype.toString.call(object[e]) === '[object Object]' ? object[e] : {}, path, value);
    } else {
        object[path[0]] = value;
    }
};

Я использую эту функцию. У меня работает.

...