【问题标题】:How to spread nested properties in Object?如何在对象中传播嵌套属性?
【发布时间】:2020-03-09 00:55:45
【问题描述】:

我在下面有这个对象。我想知道如何选择特定项目并更新属性。例如。 Item 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
      }
    };

【问题讨论】:

  • 很难帮助你,因为你在第一个代码块中的结构与你的代码不匹配。你的结构没有columnsitems,你的代码两者都有...?
  • @T.J.Crowder 他们都是抱歉的东西。
  • 请更正第一个代码块,并提供完整的示例,而不仅仅是状态对象的一部分。

标签: javascript reactjs object data-structures


【解决方案1】:

您需要使用对象键,即item-1,并为其克隆属性并为任务键添加新列表。简而言之,您需要在覆盖您希望更新的键之前在对象的每个级别进行克隆

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

【讨论】:

    【解决方案2】:

    假设起点:

    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-1task数组添加任务(这在React状态下很重要),你必须复制stateitemsitem-1,和item-1task

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

    现场示例:

    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: []
          },
        }
    };
    
    let newTask = "task-4";
    
    let newState = {
        ...state,
        items: {
            ...state.items,
            'item-1': {
                ...state.items['item-1'],
                task: [...state.items['item-1'].task, newTask]
            }
        }
    };
    
    console.log(newState);

    【讨论】:

      【解决方案3】:

      在 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 放在一个库中,这样在您的代码的未来读者看来,设置深度嵌套的值会更容易。

      【讨论】:

      • 您可能会考虑将开头更改为“这是一个用于在受 lodash 启发的对象结构中进行深度设置的实用程序(但不使用它):”或其他内容。
      猜你喜欢
      • 2018-04-16
      • 2020-09-17
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多