【问题标题】:How to modify Properties of Objects within an Array如何修改数组中对象的属性
【发布时间】:2016-11-04 09:29:49
【问题描述】:

首先请注意,这是我的 Redux 代码 HERE 提出的问题。

好吧,假设我想将“状态”的属性从“待定”编辑为“已删除”到数组中对象的特定属性,我如何使用 Object.Assign 来执行此操作以下示例:

示例a:(注意对象数组存储在对象本身中)

const plan = {
  task: [
    {
        id: 1,
        description: "This is a task",
        status: "pending"
    },
    {
        id: 2,
        description: "This is a second task",
        status: "pending"
    }
  ]
}

示例 b:(元素为对象的简单元素数组)

const task2 = [
    {
        id: 1,
        description: "This is a task",
        status: "pending"
    },
    {
        id: 2,
        description: "This is a second task",
        status: "pending"
    }
]

【问题讨论】:

  • 好点,谢谢!修好了

标签: javascript arrays object redux react-redux


【解决方案1】:

很好的问题。您打算做的态射通常被称为 Lenses(实际上是更大的态射分组)。

你可以用纯JavaScript来实现,例如:

// Return a new object with the very same structure as plan and an amended list of tasks
return Object.assign({}, plan, {
  tasks: plan.tasks.map(function (task) {
    // Map every existing task to a totally new object with the very same structure and a new status
    return Object.assign({}, task, { status: "deleted" })
  })
})

第二个例子更容易变形,检查以下代码:

return task2.map(function (task) {
  // Return a totally new object with the very same structure as task and a new status
  return Object.assign({}, task, { status: "deleted" });
})

此外,还有一些库可以完全满足您的需求,例如nanoscope

【讨论】:

    【解决方案2】:

    注意我正在使用您第一个问题中的代码

    好的,首先在您的 renderList 函数中,您需要包含一个 onclick 处理程序以在任务完成时进行注册:

    renderList() {
      return this.props.tasks.tasks.map((task) => {
        if(task.status == "pending"){
            return (
              <li key={task.id}>
                {task.id} {task.description}
                <button type="button">Finish</button>
                <button type="button">Edit</button>
                <button onClick={() => this.props.deleteTask(task.id)} type="button">Delete</button>
                </li>
              );
          }
      else return(
        <div key={task.id}>
          THIS TASK HAS BEEN DONE
        </div>
      );
    

    }); }

    接下来,在 ActionIndex.js 中,您应该记录选择了哪个操作,而不仅仅是“已删除”消息。所以把它改成这样:

    export const deleteTaskAction = (taskId) => {
            return {
                type: 'DELETE_TASK',
                payload: taskId //pass on task id
            }
        };
    

    最后,在您的 reducer-tasks.js 中,您应该在分派该操作时(通过按钮单击)更新该特定列表项的“状态”属性:

    case 'DELETE_TASK':
        let newTasks = state.tasks.map( (task) => {
            if(task.id !== action.payload) {
                return task;
            }
    
            return Object.assign({}, task, {status : "deleted"});
        });
    
        const newState = Object.assign({}, state, {tasks : newTasks});
        return newState;
    

    这应该会更新状态并将所选任务的状态从“待处理”更改为“已删除”,这应该会触发重新渲染并更改该元素。

    如果您有任何问题/问题,请告诉我

    【讨论】:

    • 啊,这清楚了很多。但是我得到 newState.tasks[action.payload] 是未定义的。我打印了 newState,它确实正确复制了对象数组。不知道那里发生了什么
    • 如果您打印 action.payload 是否已定义?
    • 是的,它定义正确,它指向正确的对象,相应地显示 id、描述和状态
    • action.payload 应该只等于 id,而不是整个对象
    • onClick={()=>this.props.deleteTask(task.id-1)} 应该只传递 id 和 payload: 动作中的任务应该只传递 id。所以在 reducer 中 action.payload 应该刚好等于索引对应的一个数字
    猜你喜欢
    • 2013-05-17
    • 2021-09-27
    • 1970-01-01
    • 2021-05-31
    • 2011-03-02
    • 1970-01-01
    • 2020-03-09
    • 2021-05-15
    • 1970-01-01
    相关资源
    最近更新 更多