【问题标题】:How to map an array , and change the state asynchrony using react-hooks如何映射数组,并使用 react-hooks 更改状态异步
【发布时间】:2019-10-28 21:56:30
【问题描述】:

我希望一个组件每 5 秒重新渲染一次,并在相应的索引处显示数组,已知数组长度正好是 10。

这是我到目前为止所做的:

const GameCard = ({ gameArray, startGame }) => {

  const [arrayIndex, setArrayIndex] = useState(0);
  let {questionWord} = gameArray[arrayIndex] ;

  useEffect(() => {

      if(!startGame) return;

      let timer = setTimeout(() => {
        if(arrayIndex === 9) return; //is this valid ?
        setArrayIndex(arrayIndex +1)} , 1500)

      return () => {
          clearTimeout(timer)
      }
  }, [arrayIndex ,startGame]);

  return (<div>{questionWord}</div>)

startGame 是一个布尔属性,在用户点击时会发生变化。

现在,这是可行的,但正如您所见,我基于 2 个变量触发了 useEffect,当我到达数组末尾时,我将在 setTimeout 内返回,从而阻止 arrayIndex 更新。

这感觉很老套,我该如何改进我的异步 useEffect? 当我们从 setTimeout 函数或 useEffect 返回时会发生什么?

【问题讨论】:

  • 虽然setTimeout 的第一个参数的返回值被忽略,但它用于更快地完成函数(=> 是的,它是有效的)。并且从useEffect 返回的函数在卸载组件之前执行,并且在再次执行相同的 useEffect 之前执行(因此在新的 setTimeout 之前调用 clearTimeout)。

标签: reactjs react-hooks


【解决方案1】:

使用functional updatessetArrayIndex((i) =&gt; i + 1) 可能很诱人:

如果新状态是使用前一个状态计算的,您可以将一个函数传递给 setState。

但是,您的代码需要使用 arrayIndex 常量的原始值,即如果在注册 setTimeout 时它是 0,那么即使在 5 秒后,您也希望它是 0

您的代码中已经存在这种情况 - 它在不同的渲染中会有所不同(每个计时器将具有不同的值,因为它是在不同的渲染中注册的),但是在计时器的注册和执行之间该值永远不会改变(见Closures)。


至于改进,甚至可以在注册新的 setTimeout 之前检测到arrayIndex === 9,如下所示:
useEffect(() => {
  if(!startGame || arrayIndex >= 9) return

  const timer = setTimeout(() => {
    setArrayIndex(arrayIndex + 1)
  }, 5000)
  return () => clearTimeout(timer)
}, [arrayIndex, startGame])

此外,如果您希望计时器减少渲染时间(即不是每次渲染后 5 秒,而是 5 秒间隔),您将需要 mutable reference 而不是不可变状态:

const arrayIndexRef = useRef(0)
const arrayIndex = arrayIndexRef.current
useEffect(() => {
  if(!startGame) return

  const timer = setInterval(() => {
    arrayIndexRef.current += 1
    if (arrayIndexRef.current >= 9) {
      clearInterval(timer)
    }
  }, 5000)
  return () => clearInterval(timer)
}, [startGame])

【讨论】:

    猜你喜欢
    • 2021-07-11
    • 1970-01-01
    • 2019-05-22
    • 2020-01-21
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 2021-12-12
    相关资源
    最近更新 更多