Subscribe on changes!

Hydration errors style attribute since vue 3.4

avatar
Feb 13th 2024

Vue version

3.4.19

Link to minimal reproduction

https://github.com/vuejs/core/discussions/10335

Steps to reproduce

  1. Create 2 DOM elements any ssr
  2. Create dependence style first element from style another, for example
<div :style="{ paddingRight: `${width + 10}px` }">
 Content
</div>

<button ref="cartButton">
Cart button
</button>
const cartButton = ref<HTMLElement>()
    const { width } = useElementSize(cartButton, undefined, {
        box: 'border-box'
    })

I tried using the onMounted hook but it doesn't seem to guarantee that the hydration process is complete, it seems like a bug. Is this really something that deserves warning?

this is more of a theoretical question, so I don't think reproduction is necessary, you can reproduce it in any minimal SSR

It seems that any style dependency on another style that changes on the client will give an error. We don't understand the concept?

What is expected?

No hydration errors

What is actually happening?

Hydration errors

Снимок экрана 2024-02-13 в 15 00 46

System Info

System:
    OS: macOS 14.3
    CPU: (8) arm64 Apple M1
    Memory: 69.20 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.5.1 - ~/.nvm/versions/node/v20.5.1/bin/node
    npm: 9.8.0 - ~/.nvm/versions/node/v20.5.1/bin/npm
  Browsers:
    Chrome: 121.0.6167.160
    Safari: 17.3
  npmPackages:
    vue: ^3.4.19 => 3.4.19

Any additional comments?

No response

avatar
Feb 13th 2024

upd. isMounted inside a component solves the problem, but should we add a check everywhere? It's almost as if :style itself is defective

:style="{ paddingRight: isMounted ? ${widthCartButton + 10}px : 0 }"

upd2. Is there some kind of lifecycle hook that would indicate the end of hydration of the entire application?

avatar
Feb 14th 2024

We don't know what useElementSize is doing underneath, please provide a runnable reproduction instead of code snippets.

avatar
Feb 16th 2024

We don't know what useElementSize is doing underneath, please provide a runnable reproduction instead of code snippets.

I made minimal reproduction: https://github.com/DaniilIsupov/reproduction-hydration In my example at App.vue I can't wait when all child components are mounted Because of this prop.count value is being updated until hydration is complete

image

avatar
Feb 16th 2024

We don't know what useElementSize is doing underneath, please provide a runnable reproduction instead of code snippets.

I made minimal reproduction: https://github.com/DaniilIsupov/reproduction-hydration In my example at App.vue I can't wait when all child components are mounted Because of this prop.count value is being updated until hydration is complete

image

Yes, this is the crux of the problem

useElementSize is a VueUse helper, but that's not important

The fact is that in large difficulty applications, some components are mounted before others, which leads to hydration errors when changing some parameters depending on the client side. In my case, VueUse useElementSize passes the width from the client and causes the style attribute of the not yet mounted component to change and throws an error

However, this is very difficult to reproduce in a minimal example, since the components are mounted almost simultaneously

Therefore, when accessing a client entity in one place, we cannot be sure that all components in which changes will occur have already been mounted and hydration has been completed