javascript - 当 useCallback 缺少依赖时 React useState 和 useCallback hook 如何工作
问题描述
我最近在学习react-hook。我在实践过程中遇到了一个让我无法理解的问题。
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
请帮我解答我的疑惑,非常感谢。
你可以在这里测试我的代码。
解决方案
组件将Demo
在其状态更改时重新渲染。因此,当您向集合添加计数状态时,它将具有大小 1:
set.add(count); // 0 in initial render, size is 1
现在,当您单击按钮时,它将使用useCallback
由 react 记忆的回调。这意味着它将首先检查是否有缓存值。因此,在第一次单击时,它没有缓存值。因此它调用它的回调来设置(更新)计数状态。现在,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
推荐阅读
- python - 太多值无法解包(预期为 2) - Django SQL 异常
- python - 将 Django 视图转换为休息服务
- python-3.x - 在多列上合并多个 Pandas 数据框
- r - R中具有多个条件的累积和?
- ssl - Google 域 CNAME 记录
- angularjs - AngualrJs:我需要在我的控制器中使用 $scope 吗?
- android - 如何在未安装 HAXM 的情况下在 AMD 上使用 Android Studio?
- flutter - 是否可以使用 sqflite 颤振强制升级数据库?
- c++ - 是否有任何原因要遮挡隐藏在对象后面的对象
- networking - 从 Minikube 访问公司资源