Subscribe on changes!

Mismatch vnode.children & node.data when use tsx

avatar
Aug 10th 2023

Vue version

3.3.4

Link to minimal reproduction

https://stackblitz.com/edit/github-pb6qhq?file=src%2Fcomponents%2Ftest-component.tsx

Steps to reproduce

just open the link,and see the console panel.

What is expected?

do not report the warnings ,and vnode.children should include all children,should not lose any useful child.

What is actually happening?

To render process will lose vnode child when and we use jsx syntax.

image

Logs:

[[Vue warn]: Hydration text mismatch:
- Client: "hello wrold my text"
- Server: "hello wrold " 
  at <TestComponent> 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouteProvider key="/" vnode= Object route= Object  ... > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <App key=3 > 
  at <NuxtRoot>





[Vue warn]: Hydration children mismatch in <div>: server rendered element contains fewer child nodes than client vdom. 
  at <TestComponent> 
  at <Index onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 
  at <RouteProvider key="/" vnode= Object route= Object  ... > 
  at <RouterView name=undefined route=undefined > 
  at <NuxtPage> 
  at <App key=3 > 
  at <NuxtRoot>](url)

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.20.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.6.10 - /usr/local/bin/pnpm
  npmPackages:
    vue: ^3.2.25 => 3.3.4

Any additional comments?

there is another issue , i reported it on nuxt issue, there has more informations about the problem.

avatar
Aug 10th 2023
image

I found the cause of this problem.

// vnode missed other children in there,it just take one child.
// and node.data of server has full text content.
const vnode = optimized ? children[i] : children[i] = normalizeVNode(children[i]);
const Canary = /* @__PURE__ */ defineComponent(
  (props) => {
    return () =>
      createVNode('div', null, [
        // It has two children,one of TextVNode,one,one of raw string.
        // It just take 'createTextVNode('Your name is: ')' and ignore 'lee' when call hydrateChildren
        createVNode('span', null, [createTextVNode('Your name is: '), "lee"])
      ])
  },
  {
    name: 'Canary',
    props: {
      name: {
        type: String
      }
    }
  }
)