使用 prevState 和 useState 钩子更新对象内部数组中的对象

Posted

技术标签:

【中文标题】使用 prevState 和 useState 钩子更新对象内部数组中的对象【英文标题】:updating object inside array inside object using prevState and the useState hook 【发布时间】:2021-10-09 01:15:12 【问题描述】:

我想删除基于id 等于传递的道具的嵌套对象。此刻,整个对象被替换。当我尝试使用 useState 更新状态时,我遗漏了一些东西,可能是我循环对象的方式?

更新:问题已关闭,以响应可用的answers 更新嵌套对象。这个问题涉及我认为是当前问题的一部分的数组。请注意此问题与forEach 的性质差异。可能需要return 语句,或者对 id 进行过滤的不同方法..

我的初始对象如下所示:


  "some_id1": [
    
      "id": 93979,
      // MORE STUFF
   
    ,
    
      "id": 93978,
      // MORE STUFF
    
  ],
  "some_id2": [
    
      "id": 93961,
      // MORE STUFF
    ,
    
      "id": 93960,
      // MORE STUFF
    
  ]

我会这样浏览每个项目:

for (const key in items) 
        if (Object.hasOwnProperty.call(items, key)) 
            const element = items[key];
            element.forEach(x => 
                if (x.id === singleItem.id) 
                    setItems(prevState => (
                        ...prevState,
                        [key]: 
                            ...prevState[key],
                            [x.id]: undefined
                        
                    ))
                
            )
        

【问题讨论】:

【参考方案1】:

可能一个简单的reduce 函数会起作用,循环遍历条目并返回一个对象

const data = "some_id1": ["id": 93979,"id": 93978],"some_id2": ["id": 93961,"id": 93960]
const remove = (id, data) => 
  return Object.entries(data).reduce((prev, [nextKey, nextValue]) => 
    return ...prev, [nextKey]: nextValue.filter((id: itemId) => id !==  itemId)
  
  , )



console.log(remove(id: 93961, data))

【讨论】:

【参考方案2】:

你的代码有3个问题:

    您正在将key 的值设置为一个对象,而items 应该有一个ID 数组。
// current
[key]: 
 ...prevState[key],
 [x.id]: undefined


// expected
[key]: prevState[key].filter(item => item.id === matchingId)
    如果您打算根据某些条件从数组中删除一个对象,您应该使用 filter,正如 Owen 的 answer 中所指出的那样,因为您正在做的是其他事情:
const a =  xyz: 123, xyz: undefined ;
console.log(a); //  xyz: undefined - it did not remove the key

    为了使您的代码更具可读性,预计会操作整个对象 items,然后使用 setItems 将其设置为一次状态 - 与在循环内多次调用 setItems 并基于一些条件。

    这使您的代码更具可预测性并减少了重新渲染。

另外,您的问题的解决方案:

// Define this somewhere
const INITIAL_STATE = 
  "some_id1": [
    
      "id": 93979
    ,
    
      "id": 93978
    
  ],
  "some_id2": [
    
      "id": 93961
    ,
    
      "id": 93960
    
  ]
;

// State initialization
const [items, setItems] = React.useState(INITIAL_STATE);

// Handler to remove the nested object with matching `id`
const removeByNestedId = (id, items) => 
  const keys = Object.keys(items);
  const updatedItems = keys.reduce((result, key) => 
    const values = items[key];
    // Since, we want to remove the object with matching id, we filter out the ones for which the id did not match. This way, the new values will not include the object with id as `id` argument passed.
    result[key] = values.filter(nestedItem => nestedItem.id !== id)
    return result;
  , );
  setItems(updatedItems);


// Usage
removeByNestedId(93961, items);

【讨论】:

度假时刚刚回来。谢谢大家。【参考方案3】:

您的方式解决方案

for (const key in items) 
    if (Object.hasOwnProperty.call(items, key)) 
        const element = items[key];
        element.forEach(x => 
            if (x.id === singleItem.id) 
                setItems(prevState => (
                    ...prevState,
                    //filter will remove the x item
                    [key]: element.filter(i => i.id !== x.id),
                ))
            
        )
    

简短的解决方案。

for(const k in items) items[k] = items[k].filter(x => x.id !== singleItemId);

const items = 
  "some_id1": [
    
      "id": 93979,   
    ,
    
      "id": 93978,
    
  ],
  "some_id2": [
    
      "id": 93961,
    ,
    
      "id": 93960,
    
  ]


const singleItemId = 93979;
for (const k in items) items[k] = items[k].filter(x => x.id !== singleItemId);

console.log(items);
//setItems(items)

【讨论】:

【参考方案4】:

您可以尝试使用功能更新。

const [data, setData] = [id:1,id:2,id:3...]

一旦您知道需要删除的 id。

setData(d=>d.filter(item=>item.id !== id));

【讨论】:

以上是关于使用 prevState 和 useState 钩子更新对象内部数组中的对象的主要内容,如果未能解决你的问题,请参考以下文章

功能组件的setState中的prevState到底是什么?

如何访问以前的状态,并使用它在单个状态设置器调用中仅更新某些对象属性?

如何用酶测试反应钩

反应钩子中的prevstate

如何使用反应钩子设置状态数组

React:“PrevState”和“=>”的代码解释[重复]