Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk3 min

Stop Nuxt SSR State Leaks: When to Use `useState` Instead of `ref()`

A ref is safe when it belongs to a component. The Nuxt SSR risk is a mutable ref created once at module scope and reused across requests.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A Vue ref() is not inherently unsafe in Nuxt. The risk is creating a mutable ref once at server module scope and sharing that object across requests. Keep component-owned state inside setup(); use Nuxt’s keyed useState when state must be shared in the Nuxt app and preserved through server rendering and hydration.

Why can Nuxt state leak between users?

With server-side rendering (SSR), a server process can handle many requests while its imported modules remain loaded. A ref created at module scope is created when that module is evaluated, rather than once for each component instance or request. If one request writes user-specific data to that ref, a later request handled by the same process can encounter the same object.

As an Amazon Associate I earn from qualifying purchases.

That is a lifetime and ownership problem, not a flaw in ref(). Nuxt’s v3 state guide warns: “Never define const state = ref() outside of <script setup> or setup() function.” Nuxt’s State Management guide illustrates the distinction between component-scoped refs and state that Nuxt manages for SSR.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The unsafe pattern: a module-level singleton

// Avoid in SSR: created once when this module is evaluated.
export const currentUser = ref<User | null>(null)

This exported object belongs to a long-lived server module, not to one request. If request A stores its user in it and request B later reads it, user-specific state can cross the request boundary. Do not put credentials, personal details, shopping carts, or other per-user mutable data in a server-wide singleton.

A safe local ref: state owned by a component

<script setup lang="ts">
const isOpen = ref(false)
</script>

A ref created in a component’s <script setup> belongs to that component instance. It is suitable for local UI state such as whether a disclosure is open. Nuxt’s warning is about defining shared ref state outside <script setup> or setup(), not about using refs generally.

When should you use useState instead?

Use useState when multiple parts of the Nuxt application need the same SSR-aware state and that state should survive hydration. Nuxt describes it as “a reactive and SSR-friendly shared state.” The Nuxt v4 useState API documentation explains its keyed state and initializer.

// composables/useCart.ts
export const useCart = () => useState<CartItem[]>('cart', () => [])

Give related consumers a stable key: calls using the same key in the same Nuxt application context refer to the shared state associated with it. The initializer supplies its initial value. This is Nuxt-managed state, not a general-purpose process-wide variable; do not substitute a global mutable singleton for request-aware state.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose by scope, sharing, and serialization

Need Use Reason
State used by one component instance ref() in setup() or <script setup> Its owner and lifetime are the component instance.
State shared by components in a Nuxt app and retained through hydration useState with a stable key Nuxt manages keyed shared state for SSR and client hydration.
Mutable user-specific state held in an imported server module Neither as a process-wide singleton; move it to an appropriate request-aware design A long-lived module object can be reused across requests.

What belongs in useState?

Nuxt serializes useState data as JSON in its payload so the client can restore state during hydration. Store JSON-serializable data, such as plain objects, arrays, strings, numbers, booleans, or null. Nuxt cautions against classes, functions, and symbols unless custom serialization is configured; see the API’s serialization guidance.

For authentication or tenant-specific state, check the boundaries of the application’s request context and data-fetching design rather than assuming that a globally mutable variable is isolated per user. A stable key identifies state within the Nuxt application context; it is not a substitute for deciding which data belongs to which request or user.

How does hydration affect the choice?

Nuxt first renders HTML on the server, then the browser hydrates the app by recreating the client-side application, matching it to the server output, and attaching event listeners. Nuxt’s v3 lifecycle guide describes the server and client lifecycle; its v4 lifecycle guide explains hydration and recommends SSR-friendly data composables.

Keep the initial server and client data consistent. If each side independently generates a different initial value, the client may not match the server-rendered output. For server-fetched data that should be reused during hydration, use Nuxt’s SSR-friendly data-fetching composables rather than inventing a separate module-level cache.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Which Nuxt version applies?

The cited v3 state guide identifies Nuxt 3.21.11 and states that Nuxt 3 reached end of life on July 31, 2026, with no further bug fixes or security patches; it directs users to Nuxt 4 or extended support. Check the Nuxt major version and support arrangement for your project before applying version-specific guidance. The core distinction here—component-owned state versus mutable state kept in a long-lived server module—is about scope and lifetime, not a particular minor-version signature.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.