【问题标题】:How to find a string from multiple objects?如何从多个对象中找到一个字符串?
【发布时间】:2019-12-10 11:03:49
【问题描述】:

我正在尝试通过传递已删除的项目 ID 来更新我的 redux reducer 中的状态。 Id 位于任务和相关列中。删除此项目的干净方法是什么?

到目前为止,我的减速器看起来像这样:

case DELETE_TASK:
  const update =  delete state.tasks[`${action.payload.id}`]
  const findIdCol = ?
  return {

  }


const initState = {
      tasks: {
        "task1": {
          id: "task1",
          content: "hello1"
        },
        "task2": {
          id: "task2",
          content: "hello2"
        },
        "task3": {
          id: "task2",
          content: "hello3"
        }
      },
      columns: {
        "column1": {
          id: "column1",
          taskIds: []
        },
        "column2": {
          id: "column2",
          taskIds: []
        },
        "column3": {
          id: "column3",
          taskIds: ["task3", "task1"]
        }
      },
      main: {
        "main": {
          id: "main",
          taskIds: ["task2"]
        }
      },
      columnOrder: ["column1", "column2", "column3"],
      mainOrder: ["main"]
    };

【问题讨论】:

  • 通过删除项目,您的意思是从任何列中删除 id 吗?如果是这种情况,过滤每一列将是一个解决方案。
  • 是的,我需要删除相关列中的 id。我相信 const update = delete state.tasks[${action.payload.id}] 会从任务中删除对象,下一步是删除列中的 id。我需要检查所有现有的列,例如列和主要
  • @Freddy :直接在状态上执行delete 或任何其他修改其属性的方式似乎都不是 clean 。相反,我会 suggest 做复制修改替换的事情。

标签: javascript reactjs redux react-redux state


【解决方案1】:

您可以将 columns 对象转换为其条目,允许您循环每个条目您可以使用 reduce 重新创建 columns 对象:

state.columns = Object.entries(state.columns).reduce((a, [k, v]) => {
  v.taskIds = v.taskIds.filter(taskId => taskId !== action.payload.id)
  a[k] = v
  return a
}, {})

演示:

const state = {
  tasks: {
    task1: { id: 'task1', content: 'hello1' },
    task2: { id: 'task2', content: 'hello2' },
    task3: { id: 'task2', content: 'hello3' }
  },
  columns: {
    column1: { id: 'column1',taskIds: [] },
    column2: { id: 'column2',taskIds: [] },
    column3: { id: 'column3',taskIds: ['task3', 'task1'] }
  },
  main: {
    main: { id: 'main', taskIds: ['task2']}
  },
  columnOrder: ['column1', 'column2', 'column3'],
  mainOrder: ['main']
}


const id = 'task1'

state.columns = Object.entries(state.columns).reduce((a, [k, v]) => {
  v.taskIds = v.taskIds.filter(taskId => taskId !== id)
  a[k] = v
  return a
}, {})

console.log(state)

在这种情况下,您可以将 id 替换为 action.payload.id

如果你想重用这段代码,你可以把它变成一个函数:

const state = {
  tasks: {
    task1: { id: 'task1', content: 'hello1' },
    task2: { id: 'task2', content: 'hello2' },
    task3: { id: 'task2', content: 'hello3' }
  },
  columns: {
    column1: { id: 'column1',taskIds: [] },
    column2: { id: 'column2',taskIds: [] },
    column3: { id: 'column3',taskIds: ['task2', 'task1'] }
  },
  main: {
    main: { id: 'main', taskIds: ['task2']}
  },
  columnOrder: ['column1', 'column2', 'column3'],
  mainOrder: ['main']
}


const id = 'task2'

const removeId = (o, id) => {
  return Object.entries(o).reduce((a, [k, v]) => {
    v.taskIds = v.taskIds.filter(taskId => taskId !== id)
    a[k] = v
    return a
  }, {})
}

state.columns = removeId(state.columns, id)
state.main = removeId(state.main, id)


console.log(state)

【讨论】:

  • 如果 task1 在 main 中怎么办?因为这只是删除位于列中的 id
  • @Freddy。您可以使用完全相同的代码,但将 state.columns 替换为 state.main
【解决方案2】:

为了保持你的 reducer 函数纯粹和状态不可变,我不建议直接更新状态的属性(reduce() 返回一个对象,delete 运算符也不行)。 这里最干净的方法是遵循模式

  • 抓住状态
  • 放入变量中
  • 修改相关部分
  • 用修改后的副本替换原始状态

这会给你一些东西,像这样(例如,如果你想从你的默认状态中删除 task3):

//dependencies
const { createStore } = Redux
     
//store initialization
const defaultState = {tasks:{"task1":{id:"task1",content:"hello1"},"task2":{id:"task2",content:"hello2"},"task3":{id:"task3",content:"hello3"}},columns:{"column1":{id:"column1",taskIds:[]},"column2":{id:"column2",taskIds:[]},"column3":{id:"column3",taskIds:["task3","task1"]}},main:{"main":{id:"main",taskIds:["task2"]}},columnOrder:["column1","column2","column3"],mainOrder:["main"]},
      appReducer = (state=defaultState, action) => {
        switch(action.type){
          case 'DELETE_TASK': {
            //destructuring state into parts to be modified
            const {tasks,columns,main} = state,
                  {payload: taskIdToDelete} = action
            //iterate through tasks to delete matching id's
            Object.entries(tasks).forEach(([key, {id}]) => id == taskIdToDelete && delete tasks[key])
            //iterate through columns to filter out deleted task           
            Object.entries(columns).forEach(([key, {taskIds}]) => columns[key]['taskIds'] = taskIds.filter(taskId => taskId != taskIdToDelete))
            //filter out deleted task from main           
            main.main.taskIds = main.main.taskIds.filter(taskId => taskId != taskIdToDelete)
            return {...state, tasks, columns, main}
          }
          default: return state
        }
      },
      store = createStore(appReducer)
//dispatch 'DELETE_TASK'
store.dispatch({type:'DELETE_TASK', payload: 'task3'})
//log modified state
console.log(store.getState())
.as-console-wrapper{min-height:100%}
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script><script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script><script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.4/redux.min.js"></script><script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.1.1/react-redux.min.js"></script><div id="root"></div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 2022-01-09
    • 1970-01-01
    • 2012-03-12
    • 2021-01-09
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多