]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
docs: use script setup
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 25 Jan 2023 13:24:19 +0000 (14:24 +0100)
committerEduardo San Martin Morote <posva@users.noreply.github.com>
Wed, 15 Feb 2023 09:52:57 +0000 (10:52 +0100)
packages/docs/cookbook/migration-v1-v2.md
packages/docs/core-concepts/actions.md
packages/docs/core-concepts/getters.md
packages/docs/core-concepts/index.md
packages/docs/core-concepts/plugins.md
packages/docs/core-concepts/state.md
packages/docs/introduction.md
packages/docs/ssr/index.md
packages/docs/ssr/nuxt.md

index 72885d3d88f80c71033afccc5dbfed2f0242f3cb..d898908c0854cd2be542c326fd1c9fee90fdf527 100644 (file)
@@ -38,41 +38,41 @@ Added in [2.0.0-rc.0](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHAN
 
 Replace any usage of the type `GenericStore` with `StoreGeneric`. This is the new generic store type that should accept any kind of store. If you were writing functions using the type `Store` without passing its generics (e.g. `Store<Id, State, Getters, Actions>`), you should also use `StoreGeneric` as the `Store` type without generics creates an empty store type.
 
-```diff
--function takeAnyStore(store: Store) {}
-+function takeAnyStore(store: StoreGeneric) {}
+```ts
+function takeAnyStore(store: Store) {} // [!code --]
+function takeAnyStore(store: StoreGeneric) {} // [!code ++]
 
--function takeAnyStore(store: GenericStore) {}
-+function takeAnyStore(store: StoreGeneric) {}
+function takeAnyStore(store: GenericStore) {} // [!code --]
+function takeAnyStore(store: StoreGeneric) {} // [!code ++]
 ```
 
 ## `DefineStoreOptions` for plugins
 
 If you were writing plugins, using TypeScript, and extending the type `DefineStoreOptions` to add custom options, you should rename it to `DefineStoreOptionsBase`. This type will apply to both setup and options stores.
 
-```diff
- declare module 'pinia' {
--  export interface DefineStoreOptions<S, Store> {
-+  export interface DefineStoreOptionsBase<S, Store> {
-     debounce?: {
-       [k in keyof StoreActions<Store>]?: number
-     }
-   }
- }
+```ts
+declare module 'pinia' {
+  export interface DefineStoreOptions<S, Store> { // [!code --]
+  export interface DefineStoreOptionsBase<S, Store> { // [!code ++]
+    debounce?: {
+      [k in keyof StoreActions<Store>]?: number
+    }
+  }
+}
 ```
 
 ## `PiniaStorePlugin` was renamed
 
 The type `PiniaStorePlugin` was renamed to `PiniaPlugin`.
 
-```diff
--import { PiniaStorePlugin } from 'pinia'
-+import { PiniaPlugin } from 'pinia'
+```ts
+import { PiniaStorePlugin } from 'pinia' // [!code --]
+import { PiniaPlugin } from 'pinia' // [!code ++]
 
--const piniaPlugin: PiniaStorePlugin = () => {
-+const piniaPlugin: PiniaPlugin = () => {
-   // ...
- }
+const piniaPlugin: PiniaStorePlugin = () => { // [!code --]
+const piniaPlugin: PiniaPlugin = () => { // [!code ++]
+  // ...
+}
 ```
 
 **Note this change can only be done after upgrading to the latest version of Pinia without deprecations**.
@@ -103,6 +103,7 @@ This is due to the modernization of dist files to support native ESM modules in
 
 - If you are using Vue CLI 4.x, upgrade your dependencies. This should include the fix below.
   - If upgrading is not possible for you, add this to your `vue.config.js`:
+
     ```js
     // vue.config.js
     module.exports = {
@@ -119,7 +120,9 @@ This is due to the modernization of dist files to support native ESM modules in
       },
     }
     ```
+
 - If you are manually handling webpack, you will have to let it know how to handle `.mjs` files:
+
   ```js
   // webpack.config.js
   module.exports = {
@@ -143,7 +146,7 @@ Pinia v2 no longer hijacks Vue Devtools v5, it requires Vue Devtools v6. Find th
 
 If you are using Nuxt, pinia has now it's dedicated Nuxt package 🎉. Install it with:
 
-```shell
+```bash
 npm i @pinia/nuxt
 # or with yarn
 yarn add @pinia/nuxt
@@ -153,26 +156,26 @@ Also make sure to **update your `@nuxtjs/composition-api` package**.
 
 Then adapt your `nuxt.config.js` and your `tsconfig.json` if you are using TypeScript:
 
-```diff
- // nuxt.config.js
- module.exports {
-   buildModules: [
-     '@nuxtjs/composition-api/module',
--    'pinia/nuxt',
-+    '@pinia/nuxt',
-   ],
- }
+```js
+// nuxt.config.js
+module.exports {
+  buildModules: [
+    '@nuxtjs/composition-api/module',
+    'pinia/nuxt', // [!code --]
+    '@pinia/nuxt', // [!code ++]
+  ],
+}
 ```
 
-```diff
- // tsconfig.json
- {
-   "types": [
-     // ...
--    "pinia/nuxt/types"
-+    "@pinia/nuxt"
-   ]
- }
+```json
+// tsconfig.json
+{
+  "types": [
+    // ...
+    "pinia/nuxt/types" // [!code --]
+    "@pinia/nuxt" // [!code ++]
+  ]
+}
 ```
 
 It is also recommended to give [the dedicated Nuxt section](../ssr/nuxt.md) a read.
index 3ba5cb5dfa388ac6fbc31c6ee82c4b1e774bcc6d..52b355d2dc849e71cda9cf018ebc05804f8f7cdd 100644 (file)
@@ -54,18 +54,19 @@ export const useUsers = defineStore('users', {
 
 You are also completely free to set whatever arguments you want and return anything. When calling actions, everything will be automatically inferred!
 
-Actions are invoked like methods:
-
-```js
-export default defineComponent({
-  setup() {
-    const store = useCounterStore()
-    // call the action as a method of the store
-    store.randomizeCounter()
-
-    return {}
-  },
-})
+Actions are invoked like function or regular methods:
+
+```vue
+<script setup>
+const store = useCounterStore()
+// call the action as a method of the store
+store.randomizeCounter()
+</script>
+
+<template>
+  <!-- Even on the template -->
+  <button @click="store.randomizeCounter()">Randomize</button>
+</template>
 ```
 
 ## Accessing other stores actions
@@ -93,20 +94,6 @@ export const useSettingsStore = defineStore('settings', {
 })
 ```
 
-## Usage with `setup()`
-
-You can directly call any action as a method of the store:
-
-```js
-export default {
-  setup() {
-    const store = useCounterStore()
-
-    store.randomizeCounter()
-  },
-}
-```
-
 ## Usage with the Options API
 
 <VueSchoolLink
@@ -138,10 +125,11 @@ export const useCounterStore = defineStore('counter', {
 
 While Composition API is not for everyone, the `setup()` hook can make using Pinia easier to work within the Options API. No extra map helper functions needed!
 
-```js
+```vue
+<script>
 import { useCounterStore } from '../stores/counter'
 
-export default {
+export default defineComponent({
   setup() {
     const counterStore = useCounterStore()
 
@@ -153,7 +141,8 @@ export default {
       console.log('New Count:', this.counterStore.count)
     },
   },
-}
+})
+</script>
 ```
 
 ### Without `setup()`
@@ -220,15 +209,11 @@ unsubscribe()
 
 By default, _action subscriptions_ are bound to the component where they are added (if the store is inside a component's `setup()`). Meaning, they will be automatically removed when the component is unmounted. If you also want to keep them after the component is unmounted, pass `true` as the second argument to _detach_ the _action subscription_ from the current component:
 
-```js
-export default {
-  setup() {
-    const someStore = useSomeStore()
-
-    // this subscription will be kept even after the component is unmounted
-    someStore.$onAction(callback, true)
+```vue
+<script setup>
+const someStore = useSomeStore()
 
-    // ...
-  },
-}
+// this subscription will be kept even after the component is unmounted
+someStore.$onAction(callback, true)
+</script>
 ```
index 6ecb9f3a9c8892c1b65808cb3acbf2a3cbd81580..95fee0a24fb00125ae96624f4748a3fc5ba28bd5 100644 (file)
@@ -42,19 +42,15 @@ export const useCounterStore = defineStore('counter', {
 Then you can access the getter directly on the store instance:
 
 ```vue
+<script setup>
+import { useCounterStore } from './counterStore'
+
+const store = useCounterStore()
+</script>
+
 <template>
   <p>Double count is {{ store.doubleCount }}</p>
 </template>
-
-<script>
-export default {
-  setup() {
-    const store = useCounterStore()
-
-    return { store }
-  },
-}
-</script>
 ```
 
 ## Accessing other getters
@@ -101,14 +97,13 @@ export const useStore = defineStore('main', {
 and use in component:
 
 ```vue
-<script>
-export default {
-  setup() {
-    const store = useStore()
+<script setup>
+import { useUserListStore } from './store'
 
-    return { getUserById: store.getUserById }
-  },
-}
+const userList = useUserListStore()
+const { getUserById } = storeToRefs(userList)
+// note you will have to use `getUserById.value` to access
+// the function within the <script setup>
 </script>
 
 <template>
@@ -153,15 +148,13 @@ export const useStore = defineStore('main', {
 
 You can directly access any getter as a property of the store (exactly like state properties):
 
-```js
-export default {
-  setup() {
-    const store = useCounterStore()
+```vue
+<script setup>
+const store = useCounterStore()
 
-    store.count = 3
-    store.doubleCount // 6
-  },
-}
+store.count = 3
+store.doubleCount // 6
+</script>
 ```
 
 ## Usage with the Options API
@@ -195,13 +188,15 @@ export const useCounterStore = defineStore('counter', {
 
 While Composition API is not for everyone, the `setup()` hook can make using Pinia easier to work with in the Options API. No extra map helper functions needed!
 
-```js
+```vue
+<script>
 import { useCounterStore } from '../stores/counter'
 
-export default {
+export default defineComponent({
   setup() {
     const counterStore = useCounterStore()
 
+    // **only return the whole store** instead of destructuring
     return { counterStore }
   },
   computed: {
@@ -209,9 +204,12 @@ export default {
       return this.counterStore.doubleCount * 2
     },
   },
-}
+})
+</script>
 ```
 
+This is useful while migrating a component from the Options API to the Composition API but **should only be a migration step**, always try not to mix both API styles within the same component.
+
 ### Without `setup()`
 
 You can use the same `mapState()` function used in the [previous section of state](./state.md#options-api) to map to getters:
index 41b7b62a49fce7d21261c0d00dc6f3826beec569..1afda0c51496bf61e4b96e166716de95e40ee34f 100644 (file)
@@ -10,8 +10,8 @@ Before diving into core concepts, we need to know that a store is defined using
 ```js
 import { defineStore } from 'pinia'
 
-// You can name the return value of `defineStore()` anything you want, 
-// but it's best to use the name of the store and surround it with `use` 
+// You can name the return value of `defineStore()` anything you want,
+// but it's best to use the name of the store and surround it with `use`
 // and `Store` (e.g. `useUserStore`, `useCartStore`, `useProductStore`)
 // the first argument is a unique id of the store across your application
 export const useAlertsStore = defineStore('alerts', {
@@ -76,21 +76,15 @@ As with [Vue's Composition API and Options API](https://vuejs.org/guide/introduc
 
 ## Using the store
 
-We are _defining_ a store because the store won't be created until `use...Store()` is called inside of `setup()`:
+We are _defining_ a store because the store won't be created until `use...Store()` is called within a component `<script setup>` (or within `setup()` **like all composables**):
 
-```js
+```vue
+<script setup>
 import { useCounterStore } from '@/stores/counter'
 
-export default {
-  setup() {
-    const store = useCounterStore()
-
-    return {
-      // you can return the whole store instance to use it in the template
-      store,
-    }
-  },
-}
+// access the `store` variable anywhere in the component ✨
+const store = useCounterStore()
+</script>
 ```
 
 :::tip
@@ -103,56 +97,38 @@ Once the store is instantiated, you can access any property defined in `state`,
 
 Note that `store` is an object wrapped with `reactive`, meaning there is no need to write `.value` after getters but, like `props` in `setup`, **we cannot destructure it**:
 
-```js
-export default defineComponent({
-  setup() {
-    const store = useCounterStore()
-    // ❌ This won't work because it breaks reactivity
-    // it's the same as destructuring from `props`
-    const { name, doubleCount } = store
-
-    name // "Eduardo"
-    doubleCount // 0
-
-    setTimeout(() => {
-      store.increment()
-    }, 1000)
-
-    return {
-      // will always be "Eduardo"
-      name,
-      // will always be 0
-      doubleCount,
-      // will also always be 0
-      doubleNumber: store.doubleCount,
-
-      // ✅ this one will be reactive
-      doubleValue: computed(() => store.doubleCount),
-    }
-  },
-})
+```vue
+<script setup>
+const store = useCounterStore()
+// ❌ This won't work because it breaks reactivity
+// it's the same as destructuring from `props`
+const { name, doubleCount } = store
+
+name // will always be "Eduardo"
+doubleCount // will always be 0
+
+setTimeout(() => {
+  store.increment()
+}, 1000)
+
+// ✅ this one will be reactive
+// 💡 but you could also just use `store.doubleCount` directly
+const doubleValue = computed(() => store.doubleCount)
+</script>
 ```
 
 In order to extract properties from the store while keeping its reactivity, you need to use `storeToRefs()`. It will create refs for every reactive property. This is useful when you are only using state from the store but not calling any action. Note you can destructure actions directly from the store as they are bound to the store itself too:
 
-```js
+```vue
+<script setup>
 import { storeToRefs } from 'pinia'
 
-export default defineComponent({
-  setup() {
-    const store = useCounterStore()
-    // `name` and `doubleCount` are reactive refs
-    // This will also create refs for properties added by plugins
-    // but skip any action or non reactive (non ref/reactive) property
-    const { name, doubleCount } = storeToRefs(store)
-    // the increment action can just be extracted
-    const { increment } = store
-
-    return {
-      name,
-      doubleCount,
-      increment,
-    }
-  },
-})
+const store = useCounterStore()
+// `name` and `doubleCount` are reactive refs
+// This will also extract refs for properties added by plugins
+// but skip any action or non reactive (non ref/reactive) property
+const { name, doubleCount } = storeToRefs(store)
+// the increment action can just be destructured
+const { increment } = store
+</script>
 ```
index 2777c034f800d3b11c075b273dc97c4b943cb1a2..ba87ba37c618d369c3af53df8e59ed066abd63fd 100644 (file)
@@ -15,8 +15,8 @@ Plugins are added to the pinia instance with `pinia.use()`. The simplest example
 ```js
 import { createPinia } from 'pinia'
 
-// add a property named `secret` to every store that is created after this plugin is installed
-// this could be in a different file
+// add a property named `secret` to every store that is created
+// after this plugin is installed this could be in a different file
 function SecretPiniaPlugin() {
   return { secret: 'the cake is a lie' }
 }
index 92adef3bfdceb5edd11452cd35837cbcb685fc7b..6751ac3d37ecf75b4c5bca6d33bd678031f59698 100644 (file)
@@ -233,21 +233,17 @@ cartStore.$subscribe((mutation, state) => {
 
 By default, _state subscriptions_ are bound to the component where they are added (if the store is inside a component's `setup()`). Meaning, they will be automatically removed when the component is unmounted. If you also want to keep them after the component is unmounted, pass `{ detached: true }` as the second argument to _detach_ the _state subscription_ from the current component:
 
-```js
-export default {
-  setup() {
-    const someStore = useSomeStore()
-
-    // this subscription will be kept even after the component is unmounted
-    someStore.$subscribe(callback, { detached: true })
+```vue
+<script setup>
+const someStore = useSomeStore()
 
-    // ...
-  },
-}
+// this subscription will be kept even after the component is unmounted
+someStore.$subscribe(callback, { detached: true })
+</script>
 ```
 
 :::tip
-You can watch the whole state on the `pinia` instance:
+You can _watch_ the whole state on the `pinia` instance with a single `watch()`:
 
 ```js
 watch(
index b22ac85f6b5d4073c9bd882f027b7d134b030a65..8596254b289379a84c9ed3f4248a0ce5b934f592 100644 (file)
@@ -49,20 +49,23 @@ export const useCounterStore = defineStore('counter', {
 
 And then you _use_ it in a component:
 
-```js
+```vue
+<script setup>
 import { useCounterStore } from '@/stores/counter'
 
-export default {
-  setup() {
-    const counter = useCounterStore()
+const counter = useCounterStore()
 
-    counter.count++
-    // with autocompletion ✨
-    counter.$patch({ count: counter.count + 1 })
-    // or using an action instead
-    counter.increment()
-  },
-}
+counter.count++
+// with autocompletion ✨
+counter.$patch({ count: counter.count + 1 })
+// or using an action instead
+counter.increment()
+</script>
+
+<template>
+  <!-- Access the state directly from the store -->
+  <div>Current Count: {{ counter.count }}</div>
+</template>
 ```
 
 You can even use a function (similar to a component `setup()`) to define a Store for more advanced use cases:
@@ -97,7 +100,7 @@ const useUserStore = defineStore('user', {
   // ...
 })
 
-export default {
+export default defineComponent({
   computed: {
     // other computed properties
     // ...
@@ -110,7 +113,7 @@ export default {
     // gives access to this.increment()
     ...mapActions(useCounterStore, ['increment']),
   },
-}
+})
 ```
 
 You will find more information about each _map helper_ in the core concepts.
index 85afe4b1ba42ce9c0fc150d2f78da736287ae897..a450522e1c078a7fb84d9dca332728eb2a6d186d 100644 (file)
@@ -6,15 +6,12 @@ If you are using **Nuxt.js,** you need to read [**these instructions**](./nuxt.m
 
 Creating stores with Pinia should work out of the box for SSR as long as you call your `useStore()` functions at the top of `setup` functions, `getters` and `actions`:
 
-```js
-export default defineComponent({
-  setup() {
-    // this works because pinia knows what application is running inside of
-    // `setup()`
-    const main = useMainStore()
-    return { main }
-  },
-})
+```vue
+<script setup>
+// this works because pinia knows what application is running inside of
+// `setup`
+const main = useMainStore()
+</script>
 ```
 
 ## Using the store outside of `setup()`
@@ -47,6 +44,18 @@ export default {
 }
 ```
 
+Note you don't need to do anything special when using `onServerPrefetch()`:
+
+```vue
+<script setup>
+const store = useStore()
+onServerPrefetch(async () => {
+  // ✅ this will work
+  await store.fetchData()
+})
+</script>
+```
+
 ## State hydration
 
 To hydrate the initial state, you need to make sure the rootState is included somewhere in the HTML for Pinia to pick it up later on. Depending on what you are using for SSR, **you should escape the state for security reasons**. We recommend using [@nuxt/devalue](https://github.com/nuxt-contrib/devalue) which is the one used by Nuxt.js:
index 8d7a6cfb9eae7814c714194dbb53bd38d2320370..096b01471365920e7b7fb3631543fc0e34ea6517 100644 (file)
@@ -10,7 +10,7 @@ yarn add pinia @pinia/nuxt
 npm install pinia @pinia/nuxt
 ```
 
-:::tip 
+:::tip
 If you're using npm, you might encounter an _ERESOLVE unable to resolve dependency tree_ error. In that case, add the following to your `package.json`:
 
 ```js
@@ -18,6 +18,7 @@ If you're using npm, you might encounter an _ERESOLVE unable to resolve dependen
   "vue": "latest"
 }
 ```
+
 :::
 
 We supply a _module_ to handle everything for you, you only need to add it to `modules` in your `nuxt.config.js` file:
@@ -49,6 +50,15 @@ export default {
 }
 ```
 
+As with `onServerPrefetch()`, you don't need to do anything special if you want to call a store action within `asyncData()`:
+
+```vue
+<script setup>
+const store = useStore()
+const { data } = await useAsyncData('user', () => store.fetchUser())
+</script>
+```
+
 ## Auto imports
 
 By default `@pinia/nuxt` exposes one single auto import: `usePinia()`, which is similar to `getActivePinia()` but works better with Nuxt. You can add auto imports to make your life easier: