Skip to content

Commit

Permalink
docs: improve useState with shared composable (nuxt#1945)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Nov 15, 2021
1 parent a4f5de5 commit 1c8b751
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 25 deletions.
62 changes: 43 additions & 19 deletions docs/content/3.docs/1.usage/2.state.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,68 @@
# State

Nuxt provides `useState` to create a globally shared state.
Nuxt provides `useState` to create a globally shared state within the context.

## `useState`
`useState` is SSR-friendly `ref` replacement in that its value will be hydrated (preserved) after server-side rendering and is shared across all components using a unique key.

Within your pages, components and plugins you can use `useState`. It can be used to create your own store implementation.
::alert{icon=⚠️}
Never define `const state = ref()` outside of `<script setup>` or `setup()` function.
Such state will be shared across all users visiting your website and can lead to memory leaks!

You can think of it as an SSR-friendly ref in that its value will be hydrated (preserved) after server-side rendering. It is shared across all components.
✅ Instead use `const useX = () => useState('x')`
::

## Usage

Within your pages, components and plugins you can use `useState`.

```js
const state = useState<T>(key: string, init?: () => T): Ref<T>
```

* **key**: A unique key ensuring that data fetching can be properly de-duplicated across requests
* **init**: A function that provides initial value for the state when it's not initiated
* **T**: (typescript only) Specify type of state

::alert{icon=👉}
**`useState` only works during `setup` or `Lifecycle Hooks`**
::

### Usage
## Shared State

```js
useState<T>(key: string, init?: () => T): Ref<T>
Using [auto imported composables](/docs/directory-structure/composables) we can define global typesafe states.

```ts [composables/states.ts]
export const useColor = () => useState<string>('color', () => 'pink')
```

* **key**: a unique key ensuring that data fetching can be properly de-duplicated across requests
* **init**: a function that provides initial value for the state when it's not initiated
```vue [app.vue]
<script setup>
const color = useColor() // Same as useState('color')
</script>
### Example
<template>
Current color: {{ color }}
</template>
```

## Example

In this example, we use a server-only plugin to find about request locale.

```ts [plugins/locale.server.ts]
import { defineNuxtPlugin, useState } from '#app'
```ts [composables/states.ts]
export const useLocale = () => useState<string>('locale', () => 'en')
```

export default defineNuxtPlugin((nuxt) => {
const locale = useState(
'locale',
() => nuxt.ssrContext.req.headers['accept-language']?.split(',')[0]
)
```ts [plugins/locale.server.ts]
export default defineNuxtPlugin((nuxtApp) => {
const locale = useLocale()
locale.value = nuxtApp.ssrContext?.req.headers['accept-language']?.split(',')[0]
})
```

```vue
```vue [app.vue]
<script setup>
const locale = useState('locale')
const locale = useLocale() // Same as useState('locale')
</script>
<template>
Expand Down
4 changes: 3 additions & 1 deletion examples/use-state/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
</template>

<script setup>
const locale = useState('locale')
// Defined in composables/stats.ts
// same as useState('locale')
const locale = useLocale()
const updateLocale = () => { locale.value = 'tlh-klingon' }
</script>
1 change: 1 addition & 0 deletions examples/use-state/composables/states.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const useLocale = () => useState<string>('locale')
8 changes: 3 additions & 5 deletions examples/use-state/plugins/locale.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { useState } from '#app'

export default defineNuxtPlugin((nuxt) => {
const locale = useState('locale')
locale.value = nuxt.ssrContext.req.headers['accept-language']?.split(',')[0]
export default defineNuxtPlugin((nuxtApp) => {
const locale = useLocale()
locale.value = nuxtApp.ssrContext?.req.headers['accept-language']?.split(',')[0]
})

0 comments on commit 1c8b751

Please sign in to comment.