请分享您的想法,参加2024 Clojure 状态调查!

欢迎!请在关于页面了解有关此功能的一些更多信息。

+1
ClojureScript
重新标记

在热重载中是否有一种方法只重新渲染受影响的 App 部分?

Figwheel 文档中只提到重新加载整个 App(这时你会失去所有组件的本地状态):https://figwheel.org/docs/hot_reloading.html#re-rendering-ui-after-saving-a-file

我还没有在 shadow-cljs 文档中找到这方面的内容。我看到的所有 App 要么根本不在热重载时重新渲染,要么重新挂载。

那么,比较热重载前后的 VDOM,并根据这种差异更新 DOM 遇到了哪些障碍?或者这已经被实现?

虽然 Figwheel/shadow-cljs 与 React/VDOM 无关,但它们不实现这种行为是预期的,但也许有一些库或明确的做法可以这样做?

2 个答案

+2

事实上,这并不是“重新挂载”,而只是更新,并不意味着替换 App 的整个 DOM。调用顶层 render 与更新组件并无区别,React 仍然会按常规执行 diff 和 patch。

by
编辑了 by
嗯,可能我应该上传一些示例仓库,但`reagent/render-component`确实会重新渲染整个应用程序。也许您有一个参考项目在手,这样我就可以比较并找出我哪里做得不对?
by
上传了最小化复现: https://github.com/fjolne/reagent-hot-reload

如果在输入字段中输入了一些文本,然后修改了标题文本,在热重载时的重新渲染将清除输入。
by
编辑了 by
在这种情况下这是预期的,因为除了DOM之外,没有地方存储输入值,因此从React的角度来看,输入中没有值。

更正:这在Reagent中仍然会发生,但Plain React中不会。我认为这与Reagent自己关于局部状态的概念有关。
但如果输入字段不在差异中,为什么它还会更新?再者,使用Reagent原子来存储数据而不是DOM时,也会有同样的行为。

编辑:看到了更正,感谢您的细致研究 :)
+2

一般来说,如fulcrore-frame等框架对状态和如何管理状态有明确的规则。使用这些规则。

在工具级别上这样做将会非常困难,这也是为什么figwheel和shadow-cljs都只处理代码的重新加载,而将状态管理留给实际应用的原因。我甚至不确定在没有完全限制您在代码中所能做的一切的情况下,能否在工具级别上完成这个任务。

我大量依赖于re-frame,但是有些情况下(简单表单、下拉列表展开状态等)使用本地状态似乎更简洁,而不必生成re-frame事件处理器/订阅。
另外,正如上面提到的,React自身也处理了这一点。那么为什么不可能只在重新加载前后状态之间进行普通的VDOM差异比较呢?
by
React 本身不会对此有任何不同处理,如果你对纯 JS 应用相同的即时热加载方法。

导致事物被“替代”的原因是,当你通过即时热加载重新定义一个函数时,`(identical? old new)` 返回 false。因此,在你的例子中,`app` 和 `form` 有“新的”定义,所以 React 会替换它们。如果你只是从 REPL 中调用 `(mount!)`,`input` 状态不会受到影响,并且“幸存”下来,因为实际的比较并没有替换实际的 DOM 节点。
by
哦,不知道比较还会针对函数本身进行,这解释了很多,谢谢!
...