Search code examples
javascriptvue.jsnuxt.jsserver-side-renderingnuxt3.js

Inconsistent variable values in Nuxt 3 components


I have a simple Vue signin/signup form. I have prepared funny dummy data for placeholders, so every time page reloads it will be displaying a random person data in my form:

<script setup lang="ts">
    const isLogin = ref(true);

    const dummyData = [
        ['Euclid', '[email protected]'],
        ['Gauss', '[email protected]'],
        ['Einstein', '[email protected]'],
    ];

    const cDummy = dummyData[Math.floor(Math.random()*dummyData.length)];
</script>

Then I use the data in cDummy const in template:

<template>
    <label v-if="!isLogin">
        <div>Name</div>
        <input type="text" :placeholder="cDummy[0]" required>
    </label>
    <label>
        <div>Email</div>
        <input type="email" :placeholder="cDummy[1]" required>
    </label>

    <a @click="isLogin = !isLogin">{{ modeLabels.switchText }}</a>
</template>

The problem is when I change reactive isLogin variable, the newly added input Name field placeholder name sometimes does not fit with dummy email. For example, the mail was [email protected] and the added name is Euclid and so on.

Why is it happening?


Solution

  • Nuxt 3 actually kind of doing rendering twice: one on server to generate immediate HTML and show at least something to site visitor and another one in browser to enable page interactivity.

    So the server calculates its own cDummy value and when it comes to browser, it calculates cDummy once again, which can be different.

    In order to fix this you need to create client-server-shared variable which can be done by using useState.

    const cDummy = useState('cDummy', () => dummyData[Math.floor(Math.random()*dummyData.length)]);
    

    It creates a reactive which value is then passed to client along with generated HTML and other data. Later in browser it uses already generated on server value instead of generating another one.

    Also, many thanks to @DarrylNoakes and @RaphaelRlt for helping me to understand what is happening!