docs: improve useState examples (#1969)

Co-authored-by: Sébastien Chopin <seb@nuxtjs.com>
This commit is contained in:
pooya parsa 2021-11-16 16:37:36 +01:00 committed by GitHub
parent f3a1ac5c59
commit 6d94158e95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 132 additions and 78 deletions

View File

@ -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
View 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>

View 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))
}

View File

@ -0,0 +1,4 @@
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
})

View 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"
}
}

View File

@ -0,0 +1,3 @@
{
"extends": "./.nuxt/tsconfig.json"
}

View File

@ -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>

View File

@ -1 +0,0 @@
export const useLocale = () => useState<string>('locale')

View File

@ -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]
})

View File

@ -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"