2024 Clojure状态调查中分享您的想法!

欢迎!有关如何工作的更多信息,请参见关于页面。

+1
ClojureScript
重新标记

是否有只重新渲染应用受影响部分的热重载方法?

Figwheel 文档只提到重新挂载整个应用(在这种情况下,组件的所有本地状态都将丢失):https://figwheel.org/docs/hot_reloading.html#re-rendering-ui-after-saving-a-file

在 shadow-cljs 文档中未找到与此相关的内容。到目前为止,我所见过的所有应用要么在热重载时根本不重新渲染,要么执行重挂载。

那么,比较热点重载前后的 VDOM 并根据此差异更新 DOM 的障碍是什么?或者它已经实现?

虽然 Figwheel/shadow-cljs 与 React/VDOM 无关,但并不期望它们实现此行为,但或许有一些库或定义良好的方法可以这样做?

2 个答案

+2

实际上并非“重新挂载”,而只是更新,这并不意味着整个应用的 DOM 都被替换。调用顶级 render 与更新组件没有区别,React 仍然像往常一样进行 diff 和 patch。


编辑
好吧,可能我应该上传一个示例仓库,但`reagent/render-component`肯定为我重新渲染了整个应用。也许您手头有一个参考项目,我可以对照找出我哪里做得不对?
已上传最小化可复现的例子: https://github.com/fjolne/reagent-hot-reload

如果输入字段中输入了文本,然后修改了标题文本,热重载后的重新渲染将会清除输入。

编辑
这种情况是可以预料的,因为输入的值没有存储在任何地方,除了DOM,所以从React的角度看,输入中没有值。

更正:这仍然在Reagent中发生,但在plain React中不是这种情况。我想这可能与Reagent关于本地状态的理解有关。
但如果输入字段不在更改日志中,为什么它还会被更新?此外,在用Reagent原子来保存数据而不是DOM的情况下,也会有同样的行为。

编辑:已看到修正,感谢调查:)
+2

通常,如fulcrore-frame之类的框架对状态及如何管理状态有明确的规则。请使用这些规则。

在工具级别执行此操作将非常困难,这也是为什么figwheel和shadow-cljs都只处理代码重新加载,而将状态管理留给实际应用程序的原因。我甚至不确定是否可以在不完全限制在代码中可以做什么的情况下,在工具级完成此操作。

我非常依赖re-frame,但在某些情况下(简单的表单、下拉菜单展开状态等)使用局部状态似乎比产生re-frame事件处理程序/订阅更简洁。
如上所述,React本身确实处理了这一点。那么为什么不可能直接输入重新加载前后的常规VDOM差异呢?
如果您将相同的重新加载方法应用于纯JS,React本身对此并没有不同的处理。

导致“替换”发生的原因是,如果你通过热重载重新定义一个函数,`(identical? old new)` 返回假值。因此,在你的示例中,`app` 和 `form` 有“新”的定义,所以 React 会替换它们。如果你只是从 REPL 中调用 `(mount!)`,则不会修改 `input` 状态,并且“存活”下来,因为实际的差异并不替换实际的 DOM 节点。
哦,不知道比较也包括了函数本身,这解释了很多,谢谢!
...