当useCallback缺少依赖项时,React useState和useCallback挂钩如何工作

时间:2019-11-16 10:17:33

标签: javascript reactjs react-hooks

我最近正在研究反应挂钩。我遇到了一个问题,使我在练习过程中无法理解。

import React, { useState, useCallback } from 'react';
const set = new Set();

function Demo() {
  const [count, setCount] = useState(0);

  const changeValue = useCallback(() => {
    setCount(count + 1);
  }, []); 

  set.add(count);
  console.log('size: ', set.size);

  return(
    <div>
      <p>Hello React Hook</p>
      <p>{count}</p>
      <button onClick={changeValue}>count++</button>
    </div>
  )
}

export default Demo;

// If you click the button multiple times, the output is:
// size: 1
// size: 2
// size: 2

我用react-hook编写了一个计时器。如我所料,显示的计数值始终为1,因为我没有将count用作useCallback的依赖项。

但是我不明白console.log('size: ', set.size)只打印了三遍,为什么?每次单击count++按钮,都会使Demo功能重新执行。因此,每次单击按钮时,是否不应该执行console.log('size: ', set.size)?但实际上,它只执行了3次。

为什么size保持2不变?我知道setCount每次都会替换一个新的count,所以size不应该增加吗?

请帮助我回答我的疑问,非常感谢。

您可以测试我的代码here

1 个答案:

答案 0 :(得分:2)

Demo组件将在其状态更改时重新呈现。因此,当您将计数状态添加到集合中时,它的大小将为1:

set.add(count); // 0 in initial render, size is 1

现在,当您单击按钮时,它将使用由react记住的回调useCallback。这意味着它将首先检查是否具有缓存的值。因此,第一次单击时就没有缓存值。因此,它调用其回调以设置(更新)计数状态。现在,count为1,并且您还将该计数添加到集合中。

set.add(count); // 1 in first click, size is 2

在随后的单击中,useCallaback已缓存了计数值,但是您尚未在useCallback挂钩的第二个参数中设置计数,因此它将仅返回1的缓存值-计数状态。并且它将始终从此返回。我再次重复一次,这次设置的大小是2。

将计数状态放入第二个参数时,您应该注意更改:

  const changeValue = useCallback(() => {
    setCount(count + 1);
  }, [count]); // we watch it on every click

现在,每次单击按钮,您将看到更改的值。


还请注意:不要混淆在单击后未调用changeValue的情况。每次都会调用useCallback,但不会更新状态:

  const changeValue = useCallback(() => {
    console.log('clicked') // logged every time on button click
    setCount(count + 1); // count state is not being watched, 
     // setCount won't update the count on following clicks
     // once it caches the state.
  },[]); // need to watch state here to update the state