在带有数组的单个函数中多次调用“useVal” - 意外行为

2024-03-16

我打电话给我的useArr在单个函数调用中多次调用函数。每次致电useArr,我正在将新的价值推向现有的arr功能。我用一个令人震惊的每个电话pause功能。

而不是渲染字符串abcde以逐步、间隔的方式,它只是覆盖前一个字母。我对引擎盖下的钩子的理解不是很好,所以如果有人能够提供见解,我将不胜感激。

为了给出一些关于我为什么要编写这个非常规代码的背景信息,如果有人想知道的话,我正在尝试模拟 websocket 如何与应用程序交互:)

const App = () => {
  const [arr, useArr] = useState([])
  return (
    <div>
      {arr}
      <button onClick={increment}>Click meh</button>
    </div>
  )
  async function increment() {
    useArr([...arr, 'a'])
    await pause()
    useArr([...arr, 'b'])
    await pause()
    useArr([...arr, 'c'])
    await pause()
    useArr([...arr, 'd'])
    await pause()
    useArr([...arr, 'e'])
    await pause()
  }
  async function pause() {
    return new Promise(_=>setTimeout(_, 500))
  }
}

export { App }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

tl;dr:你应该使用功能更新 https://reactjs.org/docs/hooks-reference.html#functional-updates syntax.

这实际上更多的是关于理解 JavaScript 闭包而不是钩子。为了演示发生了什么,这里有一些基于您的代码increment方法,但没有任何钩子——只是简单的 JavaScript。

  async function increment() {
    const arr = [];
    let nextArr = undefined;
    nextArr = [...arr, 'a'];
    await pause()
    nextArr = [...arr, 'b'];
    await pause()
    nextArr = [...arr, 'c'];
    await pause()
    nextArr = [...arr, 'd'];
    await pause()
    nextArr = [...arr, 'e'];
    await pause()
  }

在此函数结束时,您期望的值是多少nextArr to be? ['a', 'b', 'c', 'd', 'e'] or ['e'](提示:您已经在应用程序中看到了结果)

nextArr代表您传递给状态设置器的内容。

作为旁注,我建议您使用以下命名约定setArr而不是useArr设置器变量名称。useX应该为自定义钩子保留——不用于状态设置器。

您想要做的事情类似于以下内容:

  async function increment() {
    const arr = [];
    let nextArr = undefined;
    nextArr = [...arr, 'a'];
    await pause()
    nextArr = [...nextArr, 'b'];
    await pause()
    nextArr = [...nextArr, 'c'];
    await pause()
    nextArr = [...nextArr, 'd'];
    await pause()
    nextArr = [...nextArr, 'e'];
    await pause()
  }

此代码利用前一个值来创建下一个值。这功能更新 https://reactjs.org/docs/hooks-reference.html#functional-updates可以使用语法来达到这种效果。通过我建议的功能更新语法和命名更改,您的increment函数看起来像这样:

  async function increment() {
    setArr(prevArr => [...prevArr, 'a'])
    await pause()
    setArr(prevArr => [...prevArr, 'b'])
    await pause()
    setArr(prevArr => [...prevArr, 'c'])
    await pause()
    setArr(prevArr => [...prevArr, 'd'])
    await pause()
    setArr(prevArr => [...prevArr, 'e'])
    await pause()
  }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在带有数组的单个函数中多次调用“useVal” - 意外行为 的相关文章

随机推荐