简体   繁体   English

当 useCallback 缺少依赖时 React useState 和 useCallback hook 如何工作

[英]How does React useState and useCallback hook work when useCallback lacks dependencies

I am studying react-hook recently.我最近在学习react-hook。 I have encountered a problem which makes me unable to understand in the process of practice.我在实践过程中遇到了一个让我无法理解的问题。

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

I wrote a timer using react-hook.我使用 react-hook 编写了一个计时器。 As I expected, the count value shown is always 1, because I didn't use count as a dependency of useCallback.正如我所料,显示的计数值始终为 1,因为我没有使用 count 作为 useCallback 的依赖项。

But what I can't understand is console.log('size: ', set.size) only printed three times, why?但是我无法理解的是console.log('size: ', set.size)只打印了 3 次,为什么? Every time I click the count++ button, it will cause the Demo function to re-execute.每次点击count++按钮,都会导致Demo function重新执行。 So every time I click the button, shouldn't console.log('size: ', set.size) will be executed?所以每次我点击按钮时,不应该执行console.log('size: ', set.size)吗? But in fact it only executed three times.但实际上它只执行了 3 次。

And why does size keep 2 unchanged?为什么size保持 2 不变? I understand that setCount will replace a new count every time, so size should not increase?我知道setCount都会替换一个新的count ,所以size不应该增加?

Please help me answer my doubts, thank you very much.请帮我解答我的疑惑,非常感谢。

You can test my code here .你可以在这里测试我的代码。

The Demo component will re-render whenever its state is changed. Demo组件将在其 state 更改时重新渲染。 So, it will have the size 1 as you have added count state to the set:因此,当您将计数 state 添加到集合中时,它将具有大小 1:

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

Now, when you click on the button, it will use the callback useCallback that is memoized by react.现在,当您单击按钮时,它将使用由 react 记忆的回调useCallback It means it will first check if has cached value or not.这意味着它将首先检查是否有缓存值。 So, at the first click it has no cached value.因此,在第一次单击时,它没有缓存值。 And thus it calls its callback to set (update) the count state.因此它调用它的回调来设置(更新)计数 state。 Now, count is 1 and you also added the count in to the set.现在,count 为 1,并且您还将计数添加到集合中。

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

On following clicks useCallaback has cached the count value but you have not set the count in second parameter of useCallback hook and thus it will just return the cached value that is 1 - the count state.在接下来的点击中,useCallaback 已经缓存了计数值,但您没有在 useCallback 钩子的第二个参数中设置计数,因此它只会返回缓存值 1 - 计数 state。 And it will return always from this.它会永远从这里返回。 Again I repeat, this time the set size is 2.我再重复一遍,这次设置的大小是 2。

You should watch for the changes when put the count state in second argument:将计数 state 放入第二个参数时,您应该注意变化:

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

Now, you will see the changing value each time you click on the button.现在,每次单击按钮时,您都会看到变化的值。


Also note: Don't confuse the changeValue is not being called on following clicks.另请注意:不要混淆changeValue在以下点击时不会被调用。 This calls the useCallback every time but it just doesn't update the state:这每次都会调用 useCallback,但它不会更新 state:

  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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM