N
Nuxt8mo ago
Termonna

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.
No description
No description
17 Replies
manniL
manniL8mo ago
@Termonna Please provide a reproduction, e.g. via https://nuxt.new 🙂
manniL
manniL8mo ago
also, if role is neither a ref nor reactive, it will not be updated in the template
Termonna
TermonnaOP8mo ago
It's hard to reproduce, but I'll try for today role is computed from pinia:
const role = computed(() => storeToRefs(useUserStore()).role.value)
const role = computed(() => storeToRefs(useUserStore()).role.value)
manniL
manniL8mo ago
try to move the storeToRefs call out of the computed so const { role } = storeToRefs(useUserStore()) then using role
Termonna
TermonnaOP8mo ago
same behavior
No description
No description
Termonna
TermonnaOP8mo ago
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.
manniL
manniL8mo ago
I'm afraid a screen call won't replace providing a reproduction
Termonna
TermonnaOP8mo ago
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.vue
Termonna
TermonnaOP8mo ago
Also, 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)
Sandvich
Sandvich8mo ago
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
Termonna
TermonnaOP8mo ago
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.
danielroe
danielroe8mo ago
This sounds like a hydration error. At a guess, you might be outputting invalid HTML. Try with @nuxtjs/html-validator
Termonna
TermonnaOP8mo ago
@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
<div v-if="isReady"></div>
<div v-else></div>
<div v-if="isReady"></div>
<div v-else></div>
Revised
<div v-if="isReady"></div>
<div v-if="!isReady"></div>
<div v-if="isReady"></div>
<div v-if="!isReady"></div>
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)
danielroe
danielroe8mo ago
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
Termonna
TermonnaOP8mo ago
"No, the bug didn't reproduce only with vue-ssr
oneeach
oneeach8mo ago
Have you tried to use:
<LazyHeaderMarking v-if="roles === ROLES.BUYER" />
<LazyHeaderMarking v-if="roles === ROLES.BUYER" />
danielroe
danielroe8mo ago
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
Want results from more Discord servers?
Add your server