为什么 `useCallback` 不能总是返回相同的引用

2023-12-25

我不明白为什么useCallback每次更新其中一个 deps 时,总是返回一个新的引用。它导致许多重新渲染React.memo()本来可以避免的。

此实施有​​什么问题(如果有)useCallback?

export function useCallback(callback) {

    const callbackRef = useRef();

    callbackRef.current = callback;

    return useState(() =>
        (...args) => callbackRef.current(...args)
    )[0];

}

使用它而不是内置实现肯定会对性能产生显着的积极影响。

自己的结论:

没有理由不使用使用 ref 而不是构建的实现只要您意识到其中的含义,即,正如 @Bergy 所指出的,您就无法存储回调以供以后使用(在setTimeout例如)并期望回调具有与同步调用它相同的效果。
然而,在我看来,这是首选行为,所以没有缺点????。

Update:

有一个 React RFC 引入了一个内置的钩子来做到这一点。它将被称为useEvent https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md


此实施有​​什么问题(如果有)useCallback?

我怀疑当有人存储对您的回调的引用以供以后使用时,会产生意想不到的后果,因为它会改变它正在做的事情:

const { Fragment, useCallback, useState } = React;

function App() {
  const [value, setValue] = useState("");
  const printer = useCallback(() => value, [value]);
  return <div>
    <input type="text" value={value} onChange={e => setValue(e.currentTarget.value)} />
    <Example printer={printer} />
  </div>
}

function Example({printer}) {
  const [printerHistory, setHistory] = useState([]);
  return <Fragment>
    <ul>{
      printerHistory.map(printer => <li>{printer()}</li>)
    }</ul>
    <button onClick={e => setHistory([...printerHistory, printer])}>Store</button>
  </Fragment>
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://unpkg.com/[email protected] /cdn-cgi/l/email-protection/umd/react.production.min.js"></script>
<script src="https://unpkg.com/[email protected] /cdn-cgi/l/email-protection/umd/react-dom.production.min.js"></script>
<div id="root"></div>

(Sure, in this simplified demo the printer callback is nothing but a useless closure over the value itself, but you can imagine a more complex case where one could select an individual history entry and would want to use a complicated on-demand computation in the callback)

与本土人useCallback,存储在的函数printerHistory将是不同值的不同闭包,而在您的实现中,它们都是引用最新值的相同函数useCallback参数,并且仅在每次调用时打印当前值。


如需更详细的说明,请参阅useEvent提议 https://github.com/reactjs/rfcs/blob/useevent/text/0000-useevent.md#basic-example。肯定有这样的用例,比如solving https://stackoverflow.com/a/62005831/1048572 the stale https://stackoverflow.com/a/67117702/1048572 closure https://stackoverflow.com/q/55154186/1048572 problem https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function,但这与问题不同useCallback solves.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 `useCallback` 不能总是返回相同的引用 的相关文章

  • 需要禁用引导时间选择器的输入

    我正在使用 Bootstrap 时间选择器 我已经成功实施了 但我需要的是用户只能在 30 分钟间隙内插入 例如 10 00 10 30 11 00 等 为此我尝试过的是minuteStep如下图所示 效果完美 fantasyleague
  • 解释 javascript 中的奇怪行为

    我在推特上看到了这个 我也无法解释 定义一个onload函数按以下两种方式工作 1 JSFiddle http jsfiddle net 6rq9k 2 JSFiddle http jsfiddle net 6rq9k 1
  • Angular - Safari 无法正确显示 DOM

    我是 Angular 的新手 使用 Angular 4 我尝试通过在关联的组件类文件中设置属性来更新特定元素 但是 除非我尝试强制重新绘制网页 通过调整窗口大小等 否则页面不会更新 我打开检查器 看到 DOM 已更改 但显示与元素检查器中的
  • JavaScript 逻辑赋值是如何工作的?

    在 javascript 中 如果我们有一些代码 例如 var a one var b q a alert b 逻辑 OR 运算符会将 a 的值分配给 b 并且警报将为 一 这仅限于作业还是我们可以在任何地方使用它 似乎空字符串被视为与未定
  • 使用 jQuery 的 javascript 关联数组长度

    我正在使用 javascript 关联数组 例如 var testarray testarray one 1 testarray two 2 testarray three 3 我也在旁边使用jquery 如何使用 jquery 或任何其他
  • 在js中检测浏览器的最佳方法

    JavaScript 中有很多浏览器检测方法 据我所知 使用navigator userAgent或检测特征 例如XMLHttpRequest 等等 谁能告诉我哪种方法最好 最有效 如果你真的需要知道什么browser他们正在使用 你主要需
  • Hydrate with RTK Query 确实会抛出错误

    我有一个非常简单的组件来显示来自本地 API 的数据 使用 Nextjs API 路由制作 我使用 RTK 查询来获取数据 const api createApi reducerPath data baseQuery fetchBaseQu
  • 以编程方式触发 highchart 散点图上某个点的单击事件

    实际上 我有一个小要求 其中有一个带有点列表和下拉列表的散点图 当我从下拉列表中选择一个项目时 应触发其相应的数据点单击 当我在图表上选择一个数据点时 必须执行一些操作 并且下拉列表应根据选择进行更新 我们有什么办法可以做到这一点吗 我尝试
  • 如何按值删除数组中的多个项目?

    我正在尝试做一个removeAll 函数 它将删除具有该特定值 而不是索引 的数组的所有元素 当我们对循环进行任何更改时 棘手的部分就出现了 索引往往会移动 使其很难像我们想要的那样工作 并且每次更改时都重新启动循环 这在大数组上效率非常低
  • 您网站上的自定义 jQuery 脚本有多少行代码?多少才算是太多呢?

    对于我们的网站 我使用了大量 jQuery 现在我正在查看基础库顶部的 340 行 jQuery 代码 多少是太多了 我将添加更多内容 我什么时候开始尝试压缩代码并最终转向 OOP 行数并不意味着什么 重要的是你实际上在做什么 您可能拥有
  • 是否可以让 webpacks System.import 使用 ajax (用于进度事件)?

    所以我刚刚更新到 webpack 2 并进行了第一个工作设置 其中 webpack 通过查看 System import 调用自动创建块 相当甜蜜 但是 我使用 ajax 调用加载初始块 以便我可以加载时显示进度 https stackov
  • 使用默认值反应路由参数

    我正在使用 React 功能组件和 React Router v5 我正在使用 useParam 函数来获取参数 当参数不可用或未定义时 如何设置参数的默认值 我的路由器代码
  • javascript onclick 进入新窗口

    这是我的代码
  • 我将 X Y Z 坐标转换为屏幕 X Y 坐标有什么问题吗?

    我正在制作 3D 空间中弹跳的球体的 HTML5 Canvas 演示 这非常简单 每个球都有 X Y 和 Z 坐标 然后 这些坐标将转换为我在此处阅读的屏幕 X 和 Y 坐标 http answers google com answers
  • Jquery获取每个div的子子div并将信息抓取到数组中

    我有一些看起来像这样的 html div div class sub main div div
  • 在部分渲染时执行 JavaScript

    我有一些 JavaScript 代码 我想在用户单击其文件夹之一后执行 它会触发 show 操作和 show js erb 从而呈 现部分内容 Show js erb 当用户单击其文件夹之一时触发 如下所示 body append 它成功注
  • 使用 Javascript 检测 Pepper (PPAPI) Flash

    我们使用的是专有的文档查看器 它与某些 Chrome 版本中的 Pepper 版本的 Flash 配合得不太好 所以我希望能够检测到它并重定向到不同格式的相同内容 由于这个版本似乎落后于 NPAPI 版本 所以我一直在使用闪光检测 http
  • 如何使用 HTML5 Javascript Canvas 获取三个碰撞形状的交集并删除不碰撞的部分?

    我最近专门针对 KonvaJs 发布了类似的问题here https stackoverflow com questions 64603077 how can i get the intersection of three shapes c
  • 将 javascript 变量作为参数传递给 @url.Action()

    是否可以将javascript变量作为参数传递给 url Action 因为据我所知可能存在服务器和客户端问题 我的要求是我必须根据过滤器下载文件 并进行ajax调用不适用于下载文件 所以我对 url Action 进行了编码 但无法实现这
  • 允许 iframe 跨域链接到目标父框架

    我有 2 个域 域 1 上的一个页面使用 iframe 加载域 2 中的内容 如何允许来自domain2 iframe 内 的链接在domain1 的完整父框架中打开 我一直在关注IE和w3c的新沙箱属性 http www w3 org T

随机推荐

  • 在 Fabric.js 中,如何修改对象类以便所有子类都将具有新的自定义属性?

    我正在寻找一种方法来扩展基本的 Fabric Object 类 它具有自定义属性 我可以保存到 JSON 并从 JSON 加载 这些属性会一直传播到各个子类中 具体来说 我想存储一个深度属性 这样当我从 JSON 加载对象时 我将能够向对象
  • VB6 中的集中错误处理

    我有所有错误处理程序调用的以下方法 Public Function ToError strClass As String strMethod As String As String On Error GoTo errHandle ToErr
  • 如何在JavaFX中使用PauseTransition方法?

    我读了这本书 但我仍然对暂停过渡方法感到困惑 我制作了一个显示数字的标签 我希望该数字每秒都在增加 如何使用 PauseTransition A 暂停转换 http docs oracle com javase 8 javafx api j
  • 类“类型”和“对象”之间有什么关系?

    班上type是它自身的一个实例 即type是其自身的元类 我们如何定义一个类 哪个是它自身的一个实例 gt gt gt type type
  • 为什么 PHP 将 $_COOKIE 中的加号替换为空格?

    所以根据我对 PHP 和 cookie 的理解 如果我使用setcookie 函数 然后我得到一个自动 url 编码的 cookie 当我去 COOKIE数组 我应该取回 cookie 自动 url 解码 问题是 当我查看时 它似乎对 co
  • 如何使用 xgboost 模型对数据框中的单行进行预测

    我正在装修一个xgboost模型到存储在数据框中的某些数据 拟合后 我想在数据帧的单行上运行分类器 回归器的 predict 方法 下面是一个最小的示例 它在整个数据帧上预测良好 但仅在数据帧的第二行上运行时崩溃 from sklearn
  • Go:使用多种类型解组 JSON

    我在将 JSON 响应解组到结构中时遇到问题 我遇到的问题是邮政编码可以作为字符串或整数返回 如何编写一个解组方法来检查 zip 是否为 int 并强制将其存储为字符串 Struct type CustomerAddress struct
  • 是否有类似于 file:///android_asset/ 的路径指向 apps 目录?

    我正在使用 WebView 打开保存到应用程序的一些文件 有没有一种方法可以链接到运行时保存文件的应用程序目录 就像 file android asset 那样 通过链接我的意思是loadUrl path 以及正在打开的文件的 HTML 标
  • 为什么 puppeteer page.goto() 挂起?

    我在跑puppeteer in an alpine chrome带沙箱的容器 一切都完全按照文档的建议完成 我创建了一大堆不同的木偶驱动服务器 我将在没有任何参数的情况下启动 Puppeteer 除了headless false Why i
  • nx 构建命令因 TypeError 失败:无法读取未定义的属性(读取“云”)

    我正在尝试跑步nx build它工作正常 但现在停止工作了 下面是日志 vercel path0 node modules nrwl nx cloud lib nx cloud tasks runner js 20 const noClou
  • Angular7 Mat-select截距变化

    在我的用例场景中 我有一个下拉框 mat select 它填充了几个输入字段 任何更改都会以不同的方式填充字段 由于用户可以更改字段 因此我想在执行最终更改之前询问用户是否同意清除 或更改 所有字段 如果选择 否 则不会发生选择更改 并且所
  • 查找相邻多边形 - postgis 查询

    问题 我有一张充满多边形 一个国家的地区 的桌子 其中一些多边形具有可能会或可能不会被检查的特定属性 在这种情况下 该属性称为 spread checked 值为 1 现在我想运行一个查询来查找所有 检查 的多边形 就像是 SELECT F
  • Visual Basic .net 中图像的透明度?

    我的表单上有一个图片框 我向其中添加了图片 这张图片有一个透明的背景 但不幸的是 它似乎在图片框中丢失了 我猜测这是因为图片框的背景颜色属性设置为灰色 默认 但我看不到任何 透明 选项 知道我该怎么做吗 根据您想要实现的目标 有几种不同的方
  • 在python中创建一个可变长度的字符串

    我需要创建一个由空格组成的字符串 并且需要在运行时确定字符串的长度 这就是我正在做的事情 suffix join for x in range 0 max 必须有一个better方式 更clever方式 以及一个easier方式 有哪些方法
  • 我如何允许 django-merchant 接收 paypal IPN 确认?

    我发现了很多类似的问题 但似乎我仍然无法使我的设置工作 我正在尝试使用 django merchant 在我的网站上接受简单的 IPN paypal 付款 如果我理解正确的话 一旦设置正确 django merchant 应该为 PayPa
  • 操作后压缩 PDF

    我有以下问题 我从 Kyocera 扫描仪设备接收各种扫描的 PDF 文件 我必须自动操作这些 PDF 文件以便 删除文本标记中的颜色 将 PDF 转换为灰度 将其放入我们的 DMS 中 我正在使用 Bash 脚本来完成这项工作 为了删除文
  • Graphql 帖子正文“必须提供查询字符串。”

    我使用 Express graphql 中间件 我在正文行中发送以下请求 POST graphql HTTP 1 1 Host local 8083 Content Type application graphql Cache Contro
  • 在 Windows 中 grep unicode 文本文件的免费程序? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 unicode 文本文件集合 从 regedit 导出 我想提取带有特定文本的所有行 我试过
  • 用户 root @ localhost 的访问被拒绝 [重复]

    这个问题在这里已经有答案了 我正在尝试连接到 mysql 但它给出了警告 mysqli connect HY000 1045 用户 root localhost 访问被拒绝 使用密码 YES 我认为用户名和密码是正确的 因为我可以在 kom
  • 为什么 `useCallback` 不能总是返回相同的引用

    我不明白为什么useCallback每次更新其中一个 deps 时 总是返回一个新的引用 它导致许多重新渲染React memo 本来可以避免的 此实施有 什么问题 如果有 useCallback export function useCa