请在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 仍然像往常一样执行比较和修复。


编辑
好吧,可能我应该上传一些示例仓库,但 `reagent/render-component` 确实会帮我重新渲染整个应用。你可能有一个参考项目,这样我可以比较并找出我哪里做错了?
已上传最小化复现: https://github.com/fjolne/reagent-hot-reload

如果在输入字段中输入了一些文本,然后更改了标题的文本,热重载时的重渲染将清除输入。

编辑
在这种情况下这是预期的,因为输入的值没有存储在除DOM之外的地方,因此从React的角度来看,输入中没有值。

纠正:这仍在Reagent中发生,但对于纯React不是这种情况。我认为这与Reagent自己对本地状态的理解有关。
by
但是,为什么输入字段根本不在差异中时还会更新呢?使用 Reagent 原子代替 DOM 来持份数据时也会有相同的行为。

编辑:看到了修正,谢谢你的参与 :)
+2
by

通常,像 fulcro 或 re-frame 这样的框架对状态及其管理有明确的规则。请使用这些规则。

在工具级别做这件事会非常困难,这就是为什么 figwheel 和 shadow-cljs 只处理代码的重新加载,而将状态管理留给了实际的应用程序。我甚至不确定在工具级别做这件事是否可行,而不完全是限制你可以在代码中做什么。

by
我大量使用 re-frame,但在某些情况下(简单表单、下拉框展开状态等)使用局部状态而不是创建 re-frame 事件处理器/订阅似乎更简洁。
by
另外,正如上面提到的,React 本身也处理了这一点。那么为什么无法仅将前后的常规 VDOM 差异丢弃呢?
如果将相同的快速重新加载方法应用于纯JS,React自身并没有对此做出任何不同的处理。

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