Nuxt ignores boolean logic
I've encountered a bizarre and infinitely strange behavior in Nuxt3 (@3.8.0), and I don't even know how to describe it, but I've attempted to illustrate it with screenshots.
There are two divs using
v-if
and v-else
directives, and Nuxt rendered both the v-if
wrapper and the content from the v-else
block simultaneously. This should be physically impossible, as boolean logic implies either displaying the v-if
block or the v-else
block, but not displaying the v-if
block with content from the v-else
block.
Please, explain to me how this could have happened and what's under the hood of Nuxt3 to allow such behavior?
Important note:
As you can see in the screenshots, the v-if
section and the content of v-else
depend on the computed variable role
. After rendering, the role
variable changes in a way that it no longer satisfies the condition from v-if
, but it starts satisfying the condition for displaying the content inside v-else
.
Expected behavior: upon changing the role
variable, the v-if
section is ignored, and only the v-else
section with the corresponding content is used.
@moderator I apologize to the moderators for the ping, but the issue appears to be critical.17 Replies
Nuxt.new
Start a new Nuxt project
also, if
role
is neither a ref nor reactive, it will not be updated in the templateIt's hard to reproduce, but I'll try for today
role
is computed from pinia:
try to move the storeToRefs call out of the computed
so
const { role } = storeToRefs(useUserStore())
then using rolesame behavior
I understand this may sound strange, but could we have a call so I can demonstrate the screen? Reproducing it in writing is quite challenging, unfortunately.
I'm afraid a screen call won't replace providing a reproduction
I couldn't reproduce my specific bug in the sandbox, but I managed to create something similar. At least it seems to me that the cause of both my bug and the bug I created in the sandbox is the same.
In the file
/components/TheHeader.vue
on line 6
, there's a test variable called setFalseToColorize
. If it's set to false
, the expected result will occur (the background will turn red). The templates behave very strangely, apparently (this is also evident from the delays in their display).
Additionally, you can try moving the components TheTest
and TheSecondTest
out of the templates.
Furthermore, the behavior differs between the initial load (via ctrl+s) and refreshing the site display area (clicking on the refresh icon inside the sandbox).
Different forms of writing like const role = computed(() => storeToRefs(useUserStore()).role.value)
and const { role } = storeToRefs(useUserStore())
do not change the behavior
https://stackblitz.com/edit/termonna-nuxt3-boolean-bug?file=components%2FTheHeader.vueAlso, please note that the template inside the component
TheSecondTest
with the text 'the second template' never displays, whereas in the identical component TheTest
, the text 'template' inside the template does display (albeit with a delay)Ok you have stumbled onto some kind of bug here to do with templates inside of p tags.
It looks like during SSR the rendered html turns them into document fragments so they disappear but then on hydration the page renders only the first one without the document fragment explaining the pop in. Very odd behaviour. I'd probably just avoid putting <template> in p tags for now
As for your other bug the logic and timeouts and how often you call getBaseUserInfo makes it really tricky to figure out what's going on
In the real project, there are no <p> tags; instead, divs and custom components are used. In the sandbox, I only used them for line breaks and simplicity. Instead of timeouts, there are asynchronous requests.
Unfortunately, avoiding templates is not possible because this is not a pet project but rather a large production code.
I'll try to wait for a response from the developers since my team and I have encountered quite unpleasant bugs due to this strange behavior.
Thank you very much for your response.
This sounds like a hydration error. At a guess, you might be outputting invalid HTML. Try with
@nuxtjs/html-validator
@danielroe @manniL / TheAlexLichter
Hello, a quick update. I've found out that the original bug only occurs when
v-else
is present. If you replace v-else
with v-if
with the opposite condition, everything works correctly. Example:
Original
Revised
This replacement has helped us avoid incorrect rendering in our project three times already
This approach also fixes the issue with the color from the example above from StackBlitz (but doesn't address the rendering speed of templates)This is unlikely to be a Nuxt issue. You might check if it is possible to reproduce with Vue ssr and raise as issue there
"No, the bug didn't reproduce only with vue-ssr
Have you tried to use:
you can try with https://stackblitz.com/github/nuxt-contrib/vue3-ssr-starter. if that doesn't reproduce, would you create an issue and link your repro above? I'm pretty sure it's not a Nuxt bug but would want to confirm
StackBlitz
StackBlitz