hydrate-island: clear-and-replace instead of hydration walk
Islands now clear SSR children before render-to-dom and append the fresh DOM result. Avoids hydrate-mismatch errors from SSR/client attribute differences (~tw generates different class strings). The hydrating scope is set to nil (no cursor walk) so render-to-dom creates new DOM nodes instead of trying to reuse SSR elements. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -332,20 +332,25 @@
|
|||||||
(component-params comp))
|
(component-params comp))
|
||||||
(let
|
(let
|
||||||
((cursor (dict "parent" el "index" 0)))
|
((cursor (dict "parent" el "index" 0)))
|
||||||
(scope-push! "sx-hydrating" cursor)
|
(host-call el "replaceChildren")
|
||||||
|
(scope-push! "sx-hydrating" nil)
|
||||||
(cek-try
|
(cek-try
|
||||||
(fn
|
(fn
|
||||||
()
|
()
|
||||||
(with-island-scope
|
(with-island-scope
|
||||||
(fn (disposable) (append! disposers disposable))
|
(fn (disposable) (append! disposers disposable))
|
||||||
(fn () (render-to-dom (component-body comp) local nil))))
|
(fn
|
||||||
|
()
|
||||||
|
(let
|
||||||
|
((result (render-to-dom (component-body comp) local el)))
|
||||||
|
(when result (dom-append el result))))))
|
||||||
(fn
|
(fn
|
||||||
(err)
|
(err)
|
||||||
(scope-pop! "sx-hydrating")
|
(scope-pop! "sx-hydrating")
|
||||||
(log-warn
|
(log-warn
|
||||||
(str "hydrate fallback: " comp-name " — " err))
|
(str "hydrate fallback: " comp-name " — " err))
|
||||||
(let
|
(let
|
||||||
((fallback (cek-try (fn () (with-island-scope (fn (d) (append! disposers d)) (fn () (render-to-dom (component-body comp) local nil)))) (fn (err2) (let ((e (dom-create-element "div" nil))) (dom-set-text-content e (str "Island error: " comp-name "\n" err2)) e)))))
|
((fallback (dom-create-text (str "Island error: " comp-name " " err))))
|
||||||
(host-call el "replaceChildren" fallback)
|
(host-call el "replaceChildren" fallback)
|
||||||
nil)))
|
nil)))
|
||||||
(scope-pop! "sx-hydrating")
|
(scope-pop! "sx-hydrating")
|
||||||
|
|||||||
11
web/boot.sx
11
web/boot.sx
@@ -332,20 +332,25 @@
|
|||||||
(component-params comp))
|
(component-params comp))
|
||||||
(let
|
(let
|
||||||
((cursor (dict "parent" el "index" 0)))
|
((cursor (dict "parent" el "index" 0)))
|
||||||
(scope-push! "sx-hydrating" cursor)
|
(host-call el "replaceChildren")
|
||||||
|
(scope-push! "sx-hydrating" nil)
|
||||||
(cek-try
|
(cek-try
|
||||||
(fn
|
(fn
|
||||||
()
|
()
|
||||||
(with-island-scope
|
(with-island-scope
|
||||||
(fn (disposable) (append! disposers disposable))
|
(fn (disposable) (append! disposers disposable))
|
||||||
(fn () (render-to-dom (component-body comp) local nil))))
|
(fn
|
||||||
|
()
|
||||||
|
(let
|
||||||
|
((result (render-to-dom (component-body comp) local el)))
|
||||||
|
(when result (dom-append el result))))))
|
||||||
(fn
|
(fn
|
||||||
(err)
|
(err)
|
||||||
(scope-pop! "sx-hydrating")
|
(scope-pop! "sx-hydrating")
|
||||||
(log-warn
|
(log-warn
|
||||||
(str "hydrate fallback: " comp-name " — " err))
|
(str "hydrate fallback: " comp-name " — " err))
|
||||||
(let
|
(let
|
||||||
((fallback (cek-try (fn () (with-island-scope (fn (d) (append! disposers d)) (fn () (render-to-dom (component-body comp) local nil)))) (fn (err2) (let ((e (dom-create-element "div" nil))) (dom-set-text-content e (str "Island error: " comp-name "\n" err2)) e)))))
|
((fallback (dom-create-text (str "Island error: " comp-name " " err))))
|
||||||
(host-call el "replaceChildren" fallback)
|
(host-call el "replaceChildren" fallback)
|
||||||
nil)))
|
nil)))
|
||||||
(scope-pop! "sx-hydrating")
|
(scope-pop! "sx-hydrating")
|
||||||
|
|||||||
Reference in New Issue
Block a user