SolidJS:控制台日志中的“在`createRoot`或`render`之外创建的计算将永远不会被释放”消息

2023-11-27

在处理 SolidJS 项目时,您可能会开始在 JS 控制台中看到以下警告消息:

computations created outside a `createRoot` or `render` will never be disposed

SolidJS 的 Github 存储库问题中提供了一些相关信息。但读完它们后,我仍然不太确定这是怎么回事,以及我的代码是否真的做错了什么。

我设法找到它的来源,并根据文档找到修复方法。因此,我为那些在谷歌上搜索此警告消息的人提供解释和解决方案。


本质上,这是一个关于内存泄漏可能性的警告,因为在没有适当的上下文的情况下创建了反应式计算,当不再需要时会对其进行处理。

正确的上下文可以通过几种不同的方式创建。以下是我所知道的:

  • 通过使用render功能。
  • 通过使用createRoot功能。在引擎盖下render使用这个。
  • 通过使用createContext功能。

第一种是迄今为止最常见的方式,因为每个应用程序至少有一个render函数调用让整个节目开始。

那么是什么让代码“断章取义”呢?

最常见的方式可能是通过异步调用。仅当代码的同步部分完成运行时,才会创建上下文及其依赖树。这包括所有export default模块中的函数和主应用程序函数。

但是由于以下原因而稍后运行的代码setTimeout或者通过处于async函数将在此上下文之外,并且创建的任何反应式计算都不会被跟踪,并且可能会保留下来而不会被垃圾收集。

一个例子

假设您有一个数据输入屏幕并有一个Save按钮,向您的服务器发出 API 调用以保存数据。您希望通过漂亮的 HTML 格式消息向用户提供操作成功与否的反馈。

[msg,setMsg] = createSignal(<></>)

async function saveForm(){
  ...
  setMsg(<p>Saving your data.<i>Please stand by...</i></p>)
  const result=await callApi('updateUser',formData)
  if(result.ok){
    setMsg(<p>Your changes were <b>successfully</b> saved!</p> )
  } else {
    setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{result.error}</pre> )
  }
} 

...
  <div>
    ...
    <button onClick={saveForm} >Save</button>
    {msg()}
  </div>

当 API 调用返回错误时,这将产生上述警告,但其他时候则不会。为什么?

原因是 SolidJS 认为 JSX 中的代码插入是反应性的,即:需要监视和重新评估。因此,从 API 调用插入错误消息会创建反应式计算。

解决方案

我在 SolidJS 文档的最后找到了解决方案。这是一个特殊的 JSX 修饰符:/*@once*/

它可以用在大括号表达式的开头,并告诉 SolidJS 编译器明确不要使其成为反应式表达式。换句话说:当从 JSX 创建 DOM 节点时,它将评估一次且仅一次。

在上面的示例中,以下是如何使用它:

setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{/*@once*/ result.error}</pre> )

此后将不再有警告消息:)


就我而言,我有一个输入,当该输入更改时,我重新创建了 SVG 绘图。因为 SVG 创建是一项昂贵的操作,所以我在createEffect输入更改时运行的函数。debounce是一种推迟处理直到输入停止变化至少 X 时间的技术。它涉及在内部运行 SVG 生成代码setTimeout函数,因此位于主要上下文之外。使用/*@once*/我在生成的 JSX 中插入表达式的所有地方的修饰符都解决了该问题。

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

SolidJS:控制台日志中的“在`createRoot`或`render`之外创建的计算将永远不会被释放”消息 的相关文章

随机推荐

  • Liquibase 命令行在 sql 中创建 diff 更改日志

    我实际上在 Windows 上的命令行中使用 Liquibase 并且尝试创建一个表示两个数据库之间差异的 sql 脚本 不幸的是我只得到 xml 文件作为回报 你能帮助我吗 我的命令行 liquidbase bat driver com
  • 在 Swift 中添加时间偏移

    我的数据库中有很多不同的显示时间 并且希望通过创建偏移量来根据用户时区显示正确的时间 我正在获取用户与 GMT 的时区偏移量 然后首先将其转换为小时 NSTimeZone localTimeZone secondsFromGMT 60 60
  • 多核CPU上32位读取的原子性

    注意 我根据我认为可能提供帮助的人在哪里添加了标签到这个问题 所以请不要喊 在我的 VS 2017 64 位项目中 我有一个 32 位长值m lClosed 当我想更新它时 我使用其中之一Interlocked函数族 考虑这段代码 在线程
  • 在配置文件脚本中使用十六进制值设置 Powershell 颜色

    我知道我可以通过在我的个人资料中设置以下内容来更改 PowerShell 控制台颜色 Host UI RawUI BackgroundColor White Clear Host 但是 在 Powershell 控制台中 您可以转到 属性
  • ImageMagick 安全策略“PDF”阻止转换

    Imagemagick 安全策略似乎不允许我执行从 pdf 到 png 的转换 转换其他扩展名似乎可以工作 只是不能从 pdf 转换 自从安装以来 我没有更改任何 imagemagick 设置 如果操作系统很重要的话 我正在使用 Arch
  • 从 Eclipse 调试在 ScriptEngine 中运行的 Groovy 脚本

    我有一个 Groovy 脚本 其运行方式如下 File scriptFile ScriptEngine engine String script FileUtils readFileToString scriptFile Object ev
  • 以编程方式添加单词进行单词预测的问题

    我在用用户字典 Words班级的addWord功能将单词添加到词典中 以便它们可以显示在文本预测中 这些词确实存在于字典中APP ID 0并可用于默认的 Android 键盘 然而 我使用的是 Swift 键盘 它没有考虑这些词的预测 我正
  • Angular4 中的自定义字体导入

    我使用 Angular4 但在使用自定义字体时遇到问题 我尝试使用 font face 但它给了我无法找到字体文件的错误 我需要做什么才能包含此文件以便在我的组件中使用它 font face font family lcd plain sr
  • 如何“docker exec”从头构建的容器?

    我在尝试着docker exec从头开始构建的容器 例如 NATS 容器 看起来很简单 但由于它是从头开始构建的 我无法访问 bin bash bin sh以及任何此类命令 我收到错误 oci runtime error 找不到命令 找不到
  • Windows 8 Metro 应用程序文件共享访问

    我正在开发一个 Windows 8 Metro 应用程序 我们打算将其部署到我们公司内的几台平板电脑上 它不适用于 Windows 应用商店 我们需要该应用程序访问公司网络共享上的某些目录 但强制用户使用FilePicker这不是我们想要的
  • 使用什么来代替 Object.keys()?

    我需要在 Jquery 中找到一些可以在 IE8 和真实浏览器中工作的东西 我是 Jquery 的新手 以下是我在现代浏览器中运行的代码 FIELD office id on change function offices this val
  • ASP.NET MVC 子域

    我有这样的托管和域名 www EXAMPLE com 我创建了几个这样的子域 www PAGE1 EXAMPLE com www PAGE2 EXAMPLE com www PAGE3 EXAMPLE com etc 所有这些子域都指向同一
  • 如何为多个 servlet 配置 spring security?

    我想在 spring mvc 应用程序中使用 spring security 该应用程序由两个模块组成 一个 前端 和一个管理模块 两个模块都有自己的调度程序 servlet 具有不同的映射 因此它们确实有自己的 Web 上下文 但共享相同
  • MySQL查询超时:(70100):查询执行被中断

    我想执行 MySQL 查询以删除所有Wp posts表行其中post parent is a Wp posts排与post type设置为产品 So I do INSERT INTO temp SELECT DISTINCT id FROM
  • 基于 C 的应用程序/项目的文件和文件夹结构 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 基于 C 编程语言的应用程序 项目的一般结构是什么 库 包括 头文件 等等等等 班级结构是什么 在 OOps 中 需要可扩展和其他功能 类似 mai
  • NodeJS 中将字符串从 utf8 转换为 latin1

    我使用的是 Latin1 编码的数据库 无法将其更改为 UTF 8 这意味着我遇到了某些应用程序数据的问题 我正在使用 Tesseract 对文档进行 OCR tesseract 以 UTF 8 编码 并尝试使用 iconv lite 但是
  • 将内存转储到文件

    我想将一部分内存转储到文件中 一个原因是将信息保存在某个地方 另一个原因是当我的程序重新启动时再次读取它 这样做的正确方法是什么 我的第一个想法是 char start my pointer int i for i 0 i lt MEMOR
  • 过程指针,派生类型

    以下内容无法在 Intel Fortran XE 2011 中编译 TYPE type1 procedure interface1 POINTER p END TYPE type1 ABSTRACT INTERFACE integer fu
  • Firebase 错误:W/BiChannelGoogleApi:[FirebaseAuth:] getGoogleApiForMethod() 返回 Gms

    这是我的注册活动 我正在尝试使用 Firebase 创建一个 createUserWithEmailAndPassword 并向用户的个人资料添加一些详细信息 例如全名 地址和电话号码 我想在使用电子邮件和密码创建用户时在分配给新用户的 用
  • SolidJS:控制台日志中的“在`createRoot`或`render`之外创建的计算将永远不会被释放”消息

    在处理 SolidJS 项目时 您可能会开始在 JS 控制台中看到以下警告消息 computations created outside a createRoot or render will never be disposed Solid