Nuxt Guide
State Management
How reactive state is managed without an external state library.
There is no external state management library (no Pinia, no Vuex). State is managed using Vue's built-in reactivity APIs and Nuxt's useState.
Global State — useState
Use useState when state needs to be shared across multiple components or pages without prop drilling. The key string is the unique identifier — the same key anywhere in the app returns the same reactive ref.
// Set / initialize (typically in a composable or middleware)
const currentUser = useState<TUser | null>('currentUser', () => null)
// Read anywhere — same key returns the same reactive ref
const currentUser = useState<TUser | null>('currentUser')
Establish a clear set of global state keys per project:
| Key | Type | Description |
|---|---|---|
'currentUser' | TUser | null | Logged-in user object |
'currentOrganization' | any | null | Org loaded by middleware |
'tenant' | { slug: string } | null | Subdomain slug (multi-tenant only) |
'tenantNotFound' | boolean | Whether tenant org exists |
Local State — ref and reactive
Use ref for primitives and single values; reactive for objects:
// Primitives
const isLoading = ref(false)
const searchQuery = ref('')
const selectedId = ref<string | null>(null)
// Form objects — reactive so properties are individually bindable
const form = reactive({
firstName: '',
lastName: '',
email: '',
})
const errors = reactive({
firstName: '',
email: '',
})
Cookie State
Authentication tokens are stored in cookies managed by useCookie. Cookie config (expiry, secure, sameSite) comes from runtimeConfig.public.cookieConfig:
const token = useCookie<string | null>('accessToken', cookieConfig)
// Set
token.value = response.accessToken
// Clear
token.value = null
Dialog / Modal State
Modal visibility is kept as a reactive object per page — one object, multiple boolean flags:
const dialogs = reactive({
view: false,
edit: false,
delete: false,
})
// Open
dialogs.view = true
// Close (from child emit)
function onClose() {
dialogs.view = false
selected.value = null
}
Do's and Don'ts
| ✅ Do | ❌ Don't |
|---|---|
Use useState('key') for cross-component state | Create a separate store file |
Use reactive for form objects | Use ref for objects you need to destructure |
Use useCookie for tokens | Store tokens in localStorage |
Clear state on logout (null assignments) | Leave stale state after session end |
| Co-locate state with the composable that manages it | Scatter useState calls across random components |