mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-14 01:53:55 +00:00
docs: improve useState
examples (#1969)
Co-authored-by: Sébastien Chopin <seb@nuxtjs.com>
This commit is contained in:
parent
f3a1ac5c59
commit
6d94158e95
@ -27,11 +27,46 @@ const state = useState<T>(key: string, init?: () => T): Ref<T>
|
|||||||
**`useState` only works during `setup` or `Lifecycle Hooks`**
|
**`useState` only works during `setup` or `Lifecycle Hooks`**
|
||||||
::
|
::
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic usage
|
||||||
|
|
||||||
|
In this example, we use a component-local counter state. Any other component that uses `useState('counter')` shares the same reactive state.
|
||||||
|
|
||||||
|
```vue [app.vue]
|
||||||
|
<script setup>
|
||||||
|
const counter = useState('counter', () => Math.round(Math.random() * 1000))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
Counter: {{ counter }}
|
||||||
|
<button @click="counter++">
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
<button @click="counter--">
|
||||||
|
-
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
:button-link[Open on StackBlitz]{href="https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-state?terminal=dev" blank}
|
||||||
|
|
||||||
|
### Advanced Example
|
||||||
|
|
||||||
|
In this example, we use a composable that detects the user's default locale and keeps it in a `locale` state.
|
||||||
|
|
||||||
|
:button-link[Open on StackBlitz]{href="https://stackblitz.com/github/nuxt/framework/tree/main/examples/locale?terminal=dev" blank}
|
||||||
|
|
||||||
## Shared State
|
## Shared State
|
||||||
|
|
||||||
Using [auto-imported composables](/docs/directory-structure/composables) we can define global type-safe states.
|
By using [auto-imported composables](/docs/directory-structure/composables) we can define global type-safe states and import them across the app.
|
||||||
|
|
||||||
::code-group
|
```ts [composables/states.ts]
|
||||||
|
export const useCounter = () => useState<number>('counter', () => 0)
|
||||||
|
export const useColor = () => useState<string>('color', () => 'pink')
|
||||||
|
```
|
||||||
|
|
||||||
```vue [app.vue]
|
```vue [app.vue]
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -41,42 +76,4 @@ const color = useColor() // Same as useState('color')
|
|||||||
<template>
|
<template>
|
||||||
Current color: {{ color }}
|
Current color: {{ color }}
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```ts [composables/states.ts]
|
|
||||||
export const useColor = () => useState<string>('color', () => 'pink')
|
|
||||||
```
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
In this example, we use a [server-only plugin](/docs/directory-structure/plugins) to find about request locale.
|
|
||||||
|
|
||||||
::code-group
|
|
||||||
|
|
||||||
```vue [app.vue]
|
|
||||||
<script setup>
|
|
||||||
const locale = useLocale()
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
Current locale: {{ locale }}
|
|
||||||
</template>
|
|
||||||
```
|
|
||||||
|
|
||||||
```ts [composables/states.ts]
|
|
||||||
export const useLocale = () => useState<string>('locale', () => 'en')
|
|
||||||
```
|
|
||||||
|
|
||||||
```ts [plugins/locale.server.ts]
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
|
||||||
const locale = useLocale()
|
|
||||||
locale.value = locale.value ?? nuxtApp.ssrContext?.req.headers['accept-language']?.split(',')[0]
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
:button-link[Full example on StackBlitz]{href="https://stackblitz.com/github/nuxt/framework/tree/main/examples/use-state?terminal=dev" blank}
|
|
||||||
|
17
examples/locale/app.vue
Normal file
17
examples/locale/app.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
const locales = useLocales()
|
||||||
|
const locale = useLocale()
|
||||||
|
const date = useLocaleDate(new Date('2016-10-26') /* NUXT_BIRTHDAY */)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Nuxt birthday: {{ date }}</h2>
|
||||||
|
<label for="locale-chooser">Locale: </label>
|
||||||
|
<select id="locale-chooser" v-model="locale">
|
||||||
|
<option v-for="l of locales" :key="l" :value="l">
|
||||||
|
{{ l }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</template>
|
43
examples/locale/composables/locale.ts
Normal file
43
examples/locale/composables/locale.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
|
export const useLocale = () => useState<string>('locale', () => useDefaultLocale().value)
|
||||||
|
|
||||||
|
export const useDefaultLocale = (fallback = 'en-US') => {
|
||||||
|
const locale = ref(fallback)
|
||||||
|
if (process.server) {
|
||||||
|
// Learn more about the nuxtApp interface on https://v3.nuxtjs.org/docs/usage/nuxt-app#nuxtapp-interface-advanced
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
const reqLocale = nuxtApp.ssrContext?.req.headers['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',
|
||||||
|
'ko-KR',
|
||||||
|
'ar-EG',
|
||||||
|
'fa-IR',
|
||||||
|
'ja-JP-u-ca-japanese'
|
||||||
|
])
|
||||||
|
if (!locales.value.includes(locale.value)) {
|
||||||
|
locales.value.unshift(locale.value)
|
||||||
|
}
|
||||||
|
return locales
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using Intl.DateTimeFormat for language-sensitive date and time formatting
|
||||||
|
// Learn more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
|
||||||
|
export const useLocaleDate = (date: Ref<Date>, locale = useLocale()) => {
|
||||||
|
return computed(() => new Intl.DateTimeFormat(locale.value).format(date.value))
|
||||||
|
}
|
4
examples/locale/nuxt.config.ts
Normal file
4
examples/locale/nuxt.config.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { defineNuxtConfig } from 'nuxt3'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
})
|
12
examples/locale/package.json
Normal file
12
examples/locale/package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "example-locale",
|
||||||
|
"private": true,
|
||||||
|
"devDependencies": {
|
||||||
|
"nuxt3": "latest"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxi dev",
|
||||||
|
"build": "nuxi build",
|
||||||
|
"start": "node .output/server/index.mjs"
|
||||||
|
}
|
||||||
|
}
|
3
examples/locale/tsconfig.json
Normal file
3
examples/locale/tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"extends": "./.nuxt/tsconfig.json"
|
||||||
|
}
|
@ -1,31 +1,15 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const locale = useLocale()
|
const counter = useState('counter', () => Math.round(Math.random() * 1000))
|
||||||
const locales = [
|
|
||||||
'en-US',
|
|
||||||
'en-GB',
|
|
||||||
'ko-KR',
|
|
||||||
'ar-EG',
|
|
||||||
'fa-IR',
|
|
||||||
'ja-JP-u-ca-japanese'
|
|
||||||
]
|
|
||||||
if (!locales.includes(locale.value)) {
|
|
||||||
locales.unshift(locale.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Using Intl.DateTimeFormat for language-sensitive date and time formatting
|
|
||||||
// Learn more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
|
|
||||||
const NUXT_BIRTHDAY = new Date('2016-10-26')
|
|
||||||
const date = computed(() => new Intl.DateTimeFormat(locale.value).format(NUXT_BIRTHDAY))
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<h2>Nuxt birthday: {{ date }}</h2>
|
Counter: {{ counter }}
|
||||||
<label for="locale-chooser">Locale: </label>
|
<button @click="counter++">
|
||||||
<select id="locale-chooser" v-model="locale">
|
+
|
||||||
<option v-for="l of locales" :key="l" :value="l">
|
</button>
|
||||||
{{ l }}
|
<button @click="counter--">
|
||||||
</option>
|
-
|
||||||
</select>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export const useLocale = () => useState<string>('locale')
|
|
@ -1,13 +0,0 @@
|
|||||||
/**
|
|
||||||
* Nuxt will automatically read the files in your plugins directory and load them.
|
|
||||||
* You can use .server or .client in the file name to load a plugin just on server- or client-side.
|
|
||||||
* https://v3.nuxtjs.org/docs/directory-structure/plugins
|
|
||||||
*/
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
|
||||||
const locale = useLocale()
|
|
||||||
// Learn more about the nuxtApp interface on https://v3.nuxtjs.org/docs/usage/nuxt-app#nuxtapp-interface-advanced
|
|
||||||
const req = nuxtApp.ssrContext?.req
|
|
||||||
|
|
||||||
// Set default locale based request headers (browser locale)
|
|
||||||
locale.value = locale.value ?? req.headers['accept-language']?.split(',')[0]
|
|
||||||
})
|
|
@ -10109,6 +10109,14 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"example-locale@workspace:examples/locale":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "example-locale@workspace:examples/locale"
|
||||||
|
dependencies:
|
||||||
|
nuxt3: latest
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"example-module-extend-pages@workspace:examples/module-extend-pages":
|
"example-module-extend-pages@workspace:examples/module-extend-pages":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "example-module-extend-pages@workspace:examples/module-extend-pages"
|
resolution: "example-module-extend-pages@workspace:examples/module-extend-pages"
|
||||||
|
Loading…
Reference in New Issue
Block a user