如何使用钩子更改数组的状态?

How can I change the state of arrays using hooks?

我不确切知道它是什么,但我在尝试使用挂钩对数组进行最简单的状态更新时遇到了无数问题运行。

我发现唯一有效的方法是使用 useReducer 对数组执行单个更新,并在 onClick 处理程序上进行分派。在我当前的项目中,我试图在嵌套在表单提交上 运行s 的函数中的 for 循环中更新数组状态。我尝试了很多不同的解决方案,这只是我的一种尝试。

  function sessionToState(session) {
    let formattedArray = []
    for (let i = 0; i < session.length; i++) {
      formattedArray.push({ url: session[i] })
      setLinksArray([...linksArray, formattedArray[i]])
    }
  }

  // --------------------------------------------------------

  return (
    <div>
      <form
        method="post"
        onSubmit={async e => {
          e.preventDefault()

          const session = await getURLs({ populate: true })

          sessionToState(session)

          await createGroup()

我想知道我是否遗漏了什么重要的东西,或者关于如何使用挂钩处理数组的一些重要提示和技巧。如果需要任何更多信息,请随时询问。谢谢

从嵌套函数调用中调用状态 setter 时,您应该使用 functional update form of setState。在你的情况下它将是:

setLinksArray(linksArray => [...linksArray, formattedArray[i]])

目前还不清楚您遇到了什么样的问题,但上面的修复将使您免于出现 linksArray 的意外状态。

这也适用于任何状态,而不仅仅是数组。

从性能角度考虑,您不应在每次迭代时都调用 setState。您应该使用最终数组设置状态。

const sessionToState = (session) => {
  setLinksArray(
   session.map(sessionItem => ({url: sessionItem}))
  );
}

...或者如果您也想保留旧项目,您应该使用 setState 中的函数来完成...

const sessionToState = (session) => {
  setLinksArray(oldState => [
   ...oldState,
   ...session.map(sessionItem => ({url: sessionItem}))
  ]);
}

I was wondering if there are any big things that I am missing

TLDR:setLinksArray 不会在当前渲染中更新 linksArray,但会在下一次渲染中更新。


假设变量初始化如下:

const [linksArray, setLinksArray] = useState([])

提示在 const 关键字中,linksArray 是 1 个渲染中的 常量 (这个事实不会随着 let,因为这就是 useState 的工作方式)。

setLinksArray()的想法是在下一次渲染中创建一个不同的常量值

所以 for 循环类似于:

setLinksArray([...[], session0])
setLinksArray([...[], session1])
setLinksArray([...[], session2])

你会在下一个渲染中得到 linksArray = [session2]

保持理智的最佳方法是每次渲染每个状态仅调用任何 setState 函数一次(尽管您可以有多个状态),对代码的最小更改:

function sessionToState(session) {
  let formattedArray = []
  for (let i = 0; i < session.length; i++) {
    formattedArray.push({ url: session[i] })
  }
  setLinksArray(formattedArray)
}

此外,如果您需要在所有 setState 函数完成它们的工作后执行副作用(如 API 调用),即在 NEXT 渲染之后,您将需要 useEffect:

useEffect(() => {
    ...do something with updated linksArray...
}, [linksArray])

要深入了解,请参阅 https://overreacted.io/react-as-a-ui-runtime