]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
refactor(ssr): pass storeState instead of store to hydrate
authorEduardo San Martin Morote <posva13@gmail.com>
Mon, 25 Oct 2021 14:37:40 +0000 (16:37 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Mon, 25 Oct 2021 14:37:40 +0000 (16:37 +0200)
BREAKING CHANGE: the `hydrate()` option for stores defined with the
options api no longers passes the whole store instance. Instead, it
passes the `storeState` so it can be directly modified. This is because
it was currently necessary to hydrate the store by setting properties
onto `store.$state`. This change makes it impossible to make the mistake
anymore.
```diff
 defineStore('main', {
   state: () => ({
     customRef: useLocalStorage('key', 0)
   }),
-  hydrate(store) {
-    store.$state.customRef = useLocalStorage('key', 0)
+  hydrate(storeState) {
+    storeState.customRef = useLocalStorage('key', 0)
   }
 })
```

packages/pinia/__tests__/state.spec.ts
packages/pinia/src/store.ts
packages/pinia/src/types.ts

index a72140fb31c9f7ba2d77ac3a53fe81cfd6d61bf5..f614f0799d3c1e30f76749a1c361546423b44c43 100644 (file)
@@ -309,6 +309,46 @@ describe('State', () => {
       })
     }
 
+    it('hydrates custom refs options', async () => {
+      const pinia = createPinia()
+      pinia.state.value.main = { myCustom: 24, other: 'ssr' }
+
+      setActivePinia(pinia)
+
+      const useMainOptions = defineStore('main', {
+        state: () => ({ myCustom: useCustomRef(), other: 'start' }),
+        hydrate(storeState, initialState) {
+          // @ts-expect-error: cannot set as a ref
+          storeState.myCustom = useCustomRef()
+          // Object.assign(store, initialState)
+          // const { myCustom, ...rest } = initialState
+          // Object.assign(store, rest)
+        },
+      })
+
+      const main = useMainOptions()
+
+      // skips the value from hydration
+      expect(main.myCustom).toBe(0)
+      expect(main.$state.myCustom).toBe(0)
+      expect(main.other).toBe('ssr')
+      expect(main.$state.other).toBe('ssr')
+
+      expect(spy).toHaveBeenCalledTimes(0)
+      main.myCustom++
+      main.$state.myCustom++
+      main.$patch({ myCustom: 0 })
+      main.$patch((state) => {
+        state.myCustom++
+      })
+
+      expect(main.myCustom).toBe(1)
+      expect(main.$state.myCustom).toBe(1)
+      expect(main.other).toBe('ssr')
+      expect(main.$state.other).toBe('ssr')
+      expect(spy).toHaveBeenCalledTimes(4)
+    })
+
     it('hydrates custom refs setup', async () => {
       const pinia = createPinia()
       pinia.state.value.main = { myCustom: 24 }
index d30301fc2824d0460f7d9c8f819f4c435c659431..950b3bfd66ee36c1503dfecae5e309ab7ebd0651 100644 (file)
@@ -691,8 +691,15 @@ function createSetupStore<
   }
 
   // only apply hydrate to option stores with an initial state in pinia
-  if (initialState && buildState) {
-    ;(options.hydrate || innerPatch)(store, initialState)
+  if (
+    initialState &&
+    buildState &&
+    (options as DefineStoreOptions<Id, S, G, A>).hydrate
+  ) {
+    ;(options as DefineStoreOptions<Id, S, G, A>).hydrate!(
+      store.$state,
+      initialState
+    )
   }
 
   isListening = true
index 4f7ef205cc67d410c8a6f6995cb80a9e94ac0675..47376b99ed9b20d386f7ecd913493728fc94fd47 100644 (file)
@@ -654,7 +654,7 @@ export interface DefineStoreOptions<
    * Allows hydrating the store during SSR when there is an available state in
    * pinia.state.
    *
-   * @param store - the store
+   * @param storeState - the current state in the store
    * @param initialState - initialState
    */
   hydrate?(storeState: UnwrapRef<S>, initialState: UnwrapRef<S>): void