·
2 min read

When to Use useState in Nuxt

When to Use useState in Nuxt Image

Nuxt provides the useState composable, which creates a reactive and SSR-friendly shared state. It's an SSR-friendly alternative to the ref function from Vue 3.

You might be confused when to use useState or ref in your Nuxt app. In this article, I want to answer this question.

Problem with ref using SSR

Let's take a look at a simple example where we use the ref function to create a shared state in a Nuxt app:

Component.vue
<script setup lang="ts"> const createRandomString = () => { return `random-${Math.random()}`; }; const randomStrings = ref<Array<string>>([ createRandomString(), createRandomString(), createRandomString(), ]); </script> <template> <div> <ul> <li v-for="randomString of randomStrings"> {{ randomString }} </li> </ul> </div> </template>

The problem with this code is that the ref function is not SSR-friendly. The code inside the <script setup> block will be executed on the server and the client. This means that the createRandomString function will be executed twice, and we will get different random strings on the server and the client. As a result, we see a flickering effect when the page is loaded, and we get hydration mismatch warnings in the console.

Try it yourself in the following StackBlitz project. Open it in a new tab and check the console for hydration mismatch warnings. If you reload the page, you will see that the random strings are different on the server and the client. First you see the server-rendered random strings and then the client-rendered random strings after the page is hydrated:

How useState solves the problem

The useState composable from Nuxt solves exactly that problem. It creates a reactive and SSR-friendly shared state. The state is shared between the server and the client, and the useState composable ensures that the state is only created once.

Let's take a look at the same example using the useState composable:

Component.vue
<script setup lang="ts"> const createRandomString = () => { return `random-${Math.random()}`; }; const randomStrings = useState<Array<string>>('randomStrings', () => [ createRandomString(), createRandomString(), createRandomString(), ]); </script> <template> <div> <ul> <li v-for="randomString of randomStrings"> {{ randomString }} </li> </ul> </div> </template>

Try it yourself in the following StackBlitz project, and you will see that the random strings are the same on the server and the client. There are no hydration mismatch warnings in the console:

Conclusion

In general, you should use the useState composable from Nuxt when you want to create a shared state that is reactive and SSR-friendly. The useState composable ensures that the state is only created once and is shared between the server and the client.

If your Nuxt app does not require SSR, you can use the ref function from Vue 3 to create a shared state.

If you liked this article, follow me on BlueSky to get notified about my new blog posts and more content.

Alternatively (or additionally), you can subscribe to my weekly Vue & Nuxt newsletter:

I will never share any of your personal data. You can unsubscribe at any time.

If you found this article helpful.You will love these ones as well.
Rendering Dynamic Markdown in Nuxt 3+ Image

Rendering Dynamic Markdown in Nuxt 3+

Analyze Memory Leaks in Your Nuxt App Image

Analyze Memory Leaks in Your Nuxt App

Self-Host Your Nuxt App With Coolify Image

Self-Host Your Nuxt App With Coolify

Focus & Code Diff in Nuxt Content Code Blocks Image

Focus & Code Diff in Nuxt Content Code Blocks