From 31643263518f8b25683ad85191a7c8b3d708eecb Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Wed, 30 Oct 2024 11:11:55 +0900 Subject: [PATCH] fix(jsx/dom): fix dom rendering bugs for fragment. (#3569) --- src/jsx/dom/index.test.tsx | 40 ++++++++++++++++++++++++++++++++++++++ src/jsx/dom/render.ts | 23 +++++++++++++--------- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/jsx/dom/index.test.tsx b/src/jsx/dom/index.test.tsx index a1876f43..03e552fe 100644 --- a/src/jsx/dom/index.test.tsx +++ b/src/jsx/dom/index.test.tsx @@ -1119,6 +1119,46 @@ describe('DOM', () => { ) }) + it('consecutive fragment', async () => { + const ComponentA = () => { + const [count, setCount] = useState(0) + return ( + <> +
A: {count}
+ + + ) + } + const App = () => { + const [count, setCount] = useState(0) + return ( + <> + +
B: {count}
+ + + ) + } + render(, root) + expect(root.innerHTML).toBe( + '
A: 0
B: 0
' + ) + root.querySelector('#b-button')?.click() + await Promise.resolve() + expect(root.innerHTML).toBe( + '
A: 0
B: 1
' + ) + root.querySelector('#a-button')?.click() + await Promise.resolve() + expect(root.innerHTML).toBe( + '
A: 1
B: 1
' + ) + }) + it('switch child component', async () => { const Even = () =>

Even

const Odd = () =>
Odd
diff --git a/src/jsx/dom/render.ts b/src/jsx/dom/render.ts index 877493f8..2297c3af 100644 --- a/src/jsx/dom/render.ts +++ b/src/jsx/dom/render.ts @@ -368,17 +368,22 @@ const applyNodeObject = (node: NodeObject, container: Container, isNew: boolean) const childNodes = (isNew ? undefined : container.childNodes) as NodeListOf let offset: number + let insertBeforeNode: ChildNode | null = null if (isNew) { offset = -1 + } else if (!childNodes.length) { + offset = 0 } else { - offset = - (childNodes.length && - (findChildNodeIndex(childNodes, findInsertBefore(node.nN)) ?? - findChildNodeIndex( - childNodes, - next.find((n) => n.tag !== HONO_PORTAL_ELEMENT && n.e)?.e - ))) ?? - -1 + const offsetByNextNode = findChildNodeIndex(childNodes, findInsertBefore(node.nN)) + if (offsetByNextNode !== undefined) { + insertBeforeNode = childNodes[offsetByNextNode] + offset = offsetByNextNode + } else { + offset = + findChildNodeIndex(childNodes, next.find((n) => n.tag !== HONO_PORTAL_ELEMENT && n.e)?.e) ?? + -1 + } + if (offset === -1) { isNew = true } @@ -418,7 +423,7 @@ const applyNodeObject = (node: NodeObject, container: Container, isNew: boolean) // Move extra elements to the back of the container. This is to be done efficiently when elements are swapped. container.appendChild(childNodes[offset]) } else { - container.insertBefore(el, childNodes[offset] || null) + container.insertBefore(el, insertBeforeNode || childNodes[offset] || null) } } }