Skip to content

Commit

Permalink
Use a ref to track the hydrating state
Browse files Browse the repository at this point in the history
  • Loading branch information
JoviDeCroock committed Sep 28, 2024
1 parent 5f8a884 commit 882b7ac
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ function renderComponent(component) {
oldVNode._flags & MODE_HYDRATE ? [oldDom] : null,
commitQueue,
oldDom == null ? getDomSibling(oldVNode) : oldDom,
!!(oldVNode._flags & MODE_HYDRATE),
{ _: !!(oldVNode._flags & MODE_HYDRATE) },
refQueue
);

Expand Down
6 changes: 3 additions & 3 deletions src/diff/children.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { getDomSibling } from '../component';
* elements should be placed around. Likely `null` on first render (except when
* hydrating). Can be a sibling DOM element when diffing Fragments that have
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {{_: boolean}} isHydratingRef Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
*/
export function diffChildren(
Expand All @@ -36,7 +36,7 @@ export function diffChildren(
excessDomChildren,
commitQueue,
oldDom,
isHydrating,
isHydratingRef,
refQueue
) {
let i,
Expand Down Expand Up @@ -85,7 +85,7 @@ export function diffChildren(
excessDomChildren,
commitQueue,
oldDom,
isHydrating,
isHydratingRef,
refQueue
);

Expand Down
19 changes: 11 additions & 8 deletions src/diff/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import options from '../options';
* elements should be placed around. Likely `null` on first render (except when
* hydrating). Can be a sibling DOM element when diffing Fragments that have
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {{_:boolean}} isHydratingRef Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
*/
export function diff(
Expand All @@ -38,9 +38,10 @@ export function diff(
excessDomChildren,
commitQueue,
oldDom,
isHydrating,
isHydratingRef,
refQueue
) {
let isHydrating = isHydratingRef._;
/** @type {any} */
let tmp,
newType = newVNode.type;
Expand Down Expand Up @@ -253,7 +254,7 @@ export function diff(
excessDomChildren,
commitQueue,
oldDom,
isHydrating,
isHydratingRef,
refQueue
);

Expand Down Expand Up @@ -303,7 +304,7 @@ export function diff(
namespace,
excessDomChildren,
commitQueue,
isHydrating,
isHydratingRef,
refQueue
);
}
Expand Down Expand Up @@ -351,7 +352,7 @@ export function commitRoot(commitQueue, root, refQueue) {
* @param {Array<PreactElement>} excessDomChildren
* @param {Array<Component>} commitQueue List of components which have callbacks
* to invoke in commitRoot
* @param {boolean} isHydrating Whether or not we are in hydration
* @param {{_: boolean}} isHydratingRef Whether or not we are in hydration
* @param {any[]} refQueue an array of elements needed to invoke refs
* @returns {PreactElement}
*/
Expand All @@ -363,9 +364,11 @@ function diffElementNodes(
namespace,
excessDomChildren,
commitQueue,
isHydrating,
isHydratingRef,
refQueue
) {
let isHydrating = isHydratingRef._;

let oldProps = oldVNode.props;
let newProps = newVNode.props;
let nodeType = /** @type {string} */ (newVNode.type);
Expand Down Expand Up @@ -422,7 +425,7 @@ function diffElementNodes(
if (isHydrating) {
if (options._hydrationMismatch)
options._hydrationMismatch(newVNode, excessDomChildren);
isHydrating = false;
isHydratingRef._ = isHydrating = false;
}
// we created a new parent, so none of the previously attached children can be reused:
excessDomChildren = null;
Expand Down Expand Up @@ -516,7 +519,7 @@ function diffElementNodes(
excessDomChildren
? excessDomChildren[0]
: oldVNode._children && getDomSibling(oldVNode, 0),
isHydrating,
isHydratingRef,
refQueue
);

Expand Down
2 changes: 1 addition & 1 deletion src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function render(vnode, parentDom, replaceNode) {
: oldVNode
? oldVNode._dom
: parentDom.firstChild,
isHydrating,
{ _: isHydrating },
refQueue
);

Expand Down
16 changes: 16 additions & 0 deletions test/browser/hydrate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,22 @@ describe('hydrate()', () => {
expect(scratch.innerHTML).to.equal('<div class="foo">bar</div>');
});

it('should bail for adjacent trees', () => {
scratch.innerHTML = '<main><div>Hello world</div></main>';
hydrate(
<main>
<Fragment>
<span>Foo</span>
</Fragment>
<div test-id="x">Hello world</div>
</main>,
scratch
);
expect(scratch.innerHTML).to.equal(
'<main><span>Foo</span><div test-id="x">Hello world</div></main>'
);
});

it('should correctly hydrate with Fragments', () => {
const html = ul([li('1'), li('2'), li('3'), li('4')]);

Expand Down

0 comments on commit 882b7ac

Please sign in to comment.