使用 useState-hook 更改 React 中的对象数组,无需深度复制

Alter Object Array in React with useState-hook without deep copying

更改对象数组的最佳且简洁的方法是什么?

我有一个看起来像这样的代码。

const [get_post, set_post] = useState([
    {name: "First"},
    {name: "Second"},
    {name: "Third"},
  ])

我想在某个索引上添加和编辑键。所以我这样做:

 <button onClick={()=>
    set_post([...get_post, get_post[0].content = "This is index zero" ])
 }> Manipulate! </button>

我的结果是这样的:

[
    {"name": "First", "content": "This is index zero"},
    {"name": "Second"},
    {"name": "Third"},
    "This is index zero" <-- This line is the problem
]

我在谷歌上搜索了很多次,但这似乎是一个常见的主题。

这个 post 用键控对象描述了相同的问题和解决方案,这对我没有帮助。

这个 post 支持第 3 方库 and/or 深度复制,我怀疑这也不是“正确”的做法。

这个线程还支持很多深拷贝和映射,我想我不需要(它是一个数组,我应该可以通过索引来寻址我的对象)?

另一种深拷贝解决方案
https://codereview.stackexchange.com/questions/249405/react-hooks-update-array-of-object

清单还在继续...

基本上我想要没有额外行的结果,

如果可能的话:

编辑:setPost 中不需要 map 的原因。

在我的特定场景中,呈现 getPost 的模块已经是一个映射循环。试图避免嵌套循环。

(我的逻辑简化了)

const [get_post, set_post] = useState([
    {name: "First"},
    {name: "Second"},
    {name: "Third"},
  ])

//Render module
//Fixed numbers of controllers for each Object in Array.

get_post.map((post, index)=> {
<>

  <button onClick={()=>
     set_post([...get_post, get_post[index].content = "Content 1" ])}
     }> 
     Controller 1
  </button>

  <button onClick={()=>
     set_post([...get_post, get_post[index].content = "Content 2" ])}
     }> 
     Controller 2
  </button>

  <button onClick={()=>
     set_post([...get_post, get_post[index].content = "Content 3" ])}
     }> 
     Controller 3
  </button>

//...

</>
})

如果您只想更改第一个 属性,请先从数组中提取它。

您可以使用 functional updates 方法访问当前状态值,并 return 一个具有您想要的更改的新值。

set_post(([ first, ...others ]) => [{
  ...first,
  content: "This is index zero"
}, ...others])

要更改任何特定索引,您可以map将当前数组更改为一个新数组,在到达目标索引时为它创建一个新对象

let x = the_target_index

set_post(posts => posts.map((post, i) => i === x ? {
  ...post,
  content: `This is index ${x}`
} : post))

与您在 中似乎想要做的事情相匹配的稍微不同的版本是

set_post(posts => {
  posts[x] = { ...posts[x], content: `This is index ${x}` }
  // or even something like
  // posts[x].content = `This is index ${x}`

  return [...posts] // clone the array
})

我找到了一个有效的解决方案!
我没有在其他地方看到这个帖子,所以研究一下可能会很有趣。

要按索引更改或添加 key/value 到数组中的对象,只需执行以下操作:

    <button onClick={() => {
      set_post( [...get_post , get_post[index].content = "my content" ] )
      set_post( [...get_post ] ) //<-- this line removes the last input
    }
      }>

正如 Phil 所写,前面的代码被解释为:

const val = "This is index zero"; 
get_post[0].content = val; 
get_post.push(val);

这似乎删除了最新的 get_post.push(val)

根据 React 文档,可以对状态进行批处理和缓冲以实现性能

https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly

当 React 批处理时 set_post 它应该表现得像这样。

如果一行命令

set_post( [...get_post , get_post[index].content = "my content" ] ) 

给予

const val = "This is index zero"; 
get_post[0].content = val; 
get_post.push(val);

双重注入将触发缓冲区并在 array.push() 结束时重新注入状态。像这样。

var buffer = get_post
buffer[0].content = val
//Other updated to get_post...
get_post = buffer //(not push)

至此,这应该是一个完美的解决方案。