如何在对象中传播嵌套属性?

时间:2019-11-13 09:02:32

标签: javascript reactjs object data-structures

我在下面有这个对象。我想知道如何选择特定项目并更新属性。例如。项目1我想在数组中添加一个任务。

item: {
  'item-1': {
    id: 'item-1',
    title: 'To do',
    task: ['task-1', 'task-2', 'task-3', 'task-4']
  },
  'item-2': {
    id: 'item-2',
    title: 'In progress',
    task: []
  },

我目前有

const getItem = {...state.items['item-1']}
const newTaskList = [...getItem.task, newTask.id]

const newState = {
      ...state,
      items: {
        ...state.items,
        //How do I spread new array correctly in item 1?
        //...state.items['item-1'].task
      }
    };

3 个答案:

答案 0 :(得分:1)

您需要使用对象键,即item-1并为其克隆属性,并为任务键添加新列表。简而言之,您需要先克隆对象的每个级别,然后再覆盖要更新的密钥

const newState = {
  ...state,
  items: {
    ...state.items,
    'item-1': {
         ...state.items['item-1'],
         task: newTaskList
     }
  }
};

答案 1 :(得分:1)

假设起点:

let state = {
    items: {
      'item-1': {
        id: 'item-1',
        title: 'To do',
        task: ['task-1', 'task-2', 'task-3', 'task-4']
      },
      'item-2': {
        id: 'item-2',
        title: 'In progress',
        task: []
      },
    }
};

如果您想在item-1的{​​{1}}数组中添加任务而不修改原位(这在React状态下很重要),则必须复制task,{{ 1}},stateitems的{​​{1}}:

item-1

实时示例:

item-1

答案 2 :(得分:-1)

在lodadash中,您可以从对象获取并设置嵌套对象,这是我自己的实现:

//helper to get prop from object
const get = (object, path, defaultValue) => {
  const recur = (object, path) => {
    if (object === undefined) {
      return defaultValue;
    }
    if (path.length === 0) {
      return object;
    }
    return recur(object[path[0]], path.slice(1));
  };
  return recur(object, path);
};
//helper to set nested prop in object
const set = (
  state,
  statePath,
  modifier
) => {
  const recur = (result, path) => {
    const key = path[0];
    if (path.length === 0) {
      return modifier(get(state, statePath));
    }
    return Array.isArray(result)
      ? result.map((item, index) =>
          index === Number(key)
            ? recur(item, path.slice(1))
            : item
        )
      : {
          ...result,
          [key]: recur(result[key], path.slice(1)),
        };
  };
  const newState = recur(state, statePath);
  return get(state, statePath) === get(newState, statePath)
    ? state
    : newState;
};

let state = {
  items: {
    'item-1': {
      id: 'item-1',
      title: 'To do',
      task: ['task-1', 'task-2', 'task-3', 'task-4'],
    },
    'item-2': {
      id: 'item-2',
      title: 'In progress',
      task: [],
    },
  },
};
console.log(
  set(
    state,
    ['items','item-1','task'],
    (tasks)=>tasks.concat('new task')
  )
);

您可以将get和set放在一个库中,这会使设置深层嵌套的值更容易在以后的代码读者中看到。