--- navigation.icon: uil:database description: Nuxt provides powerful state management libraries and the useState composable to create a reactive and SSR-friendly shared state. --- # State Management Nuxt provides the `useState` composable to create a reactive and SSR-friendly shared state across components. `useState` is an SSR-friendly [`ref`](https://vuejs.org/api/reactivity-core.html#ref) replacement. Its value will be preserved after server-side rendering (during client-side hydration) and shared across all components using a unique key. ::ReadMore{link="/docs/api/composables/use-state"} :: ::alert{icon=👉} `useState` only works during `setup` or [`Lifecycle Hooks`](https://vuejs.org/api/composition-api-lifecycle.html#composition-api-lifecycle-hooks). :: ::alert{type=warning} Because the data inside `useState` will be serialized to JSON, it is important that it does not contain anything that cannot be serialized, such as classes, functions or symbols. :: ## Best Practices ::alert{type=danger icon=🚨} Never define `const state = ref()` outside of ` ``` ::LinkExample{link="/docs/examples/features/state-management"} :: ::ReadMore{link="/docs/api/composables/use-state"} :: ::alert{icon=📘} To globally invalidate cached state, see [`clearNuxtState`](/docs/api/utils/clear-nuxt-state). :: ### Advanced Usage In this example, we use a composable that detects the user's default locale from the HTTP request headers and keeps it in a `locale` state. ```ts [composables/locale.ts] import type { Ref } from 'vue' export const useLocale = () => useState('locale', () => useDefaultLocale().value) export const useDefaultLocale = (fallback = 'en-US') => { const locale = ref(fallback) if (process.server) { const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0] if (reqLocale) { locale.value = reqLocale } } else if (process.client) { const navLang = navigator.language if (navLang) { locale.value = navLang } } return locale } export const useLocales = () => { const locale = useLocale() const locales = ref([ 'en-US', 'en-GB', ... 'ja-JP-u-ca-japanese' ]) if (!locales.value.includes(locale.value)) { locales.value.unshift(locale.value) } return locales } export const useLocaleDate = (date: Ref | Date, locale = useLocale()) => { return computed(() => new Intl.DateTimeFormat(locale.value, { dateStyle: 'full' }).format(unref(date))) } ``` ```vue [app.vue] ``` ::LinkExample{link="/docs/examples/advanced/locale"} :: ## Shared State By using [auto-imported composables](/docs/guide/directory-structure/composables) we can define global type-safe states and import them across the app. ```ts [composables/states.ts] export const useCounter = () => useState('counter', () => 0) export const useColor = () => useState('color', () => 'pink') ``` ```vue [app.vue] ``` ## Using third-party libraries Nuxt **used to rely** on the Vuex library to provide global state management. If you are migrating from Nuxt 2, please head to [the migration guide](/docs/migration/configuration#vuex). Nuxt is not opinionated about state management, so feel free to choose the right solution for your needs. There are multiple integrations with the most popular state management libraries, including: - [Pinia](/modules/pinia) - the official Vue recommendation - [Harlem](/modules/harlem) - immutable global state management - [XState](/modules/xstate) - state machine approach with tools for visualizing and testing your state logic