HomeBlogErrors / FixesMy Component
Errors / FixesSeptember 5, 20264 min

My Component

Nuxt - How to Load Data in SSR Using Pinia Store? ## Introduction Pinia is a popular state management solution for Vue.js, which also supports Server-Side Rendering (SSR). However,...

Nuxt - How to Load Data in SSR Using Pinia Store?

Introduction

Pinia is a popular state management solution for Vue.js, which also supports Server-Side Rendering (SSR). However, when trying to load data during the SSR phase, issues may arise. In this article, we will explore how to correctly load data using Pinia Store in SSR and address the "Hydration completed but contains mismatches" error.

Why Loading Data in SSR Matters?

Loading data during the SSR phase ensures fast page loading and improves application performance. This is particularly important for applications with large amounts of data or complex logic.

Example Pinia Store with SSR

Let's start with an example of a Pinia Store that loads data during the SSR phase:

// store/myStore.js
import { defineStore } from 'pinia';
import { useNuxtApp } from '#app';

export const useMyStore = defineStore('myStore', {
  state: () => ({
    items: ref([]),
    loading: ref(false),
    error: ref(null)
  }),
  actions: {
    async fetchItems() {
      if (this.items?.length > 0) {
        return;
      }
      this.loading = true;

      const $appConfig = useNuxtApp();
      const apiUrl = $appConfig.api?.url;

      try {
        const data = await $fetch(`${apiUrl}/reference-data/airports/`);
        this.items = data;
      } catch (err) {
        this.error = err;
      } finally {
        this.loading = false;
      }
    }
  },
  persist: {
    storage: piniaPluginPersistedstate.sessionStorage()
  }
});

This example demonstrates the basic structure of a Pinia Store that loads data from an API during the SSR phase. Let's delve into why the "Hydration completed but contains mismatches" error might occur.

The "Hydration completed but contains mismatches" Error

The "Hydration completed but contains mismatches" error usually indicates that the client-side and server-side HTML do not match. This can be due to differences in the loaded data between the server and the client.

Causes of the Error

  1. Data Mismatch: If data is only loaded on the server, it may differ from the data loaded on the client.
  2. Loading Order: If data is loaded after Vue components are initialized, it can cause conflicts.
  3. Conditional Expressions: Using conditional expressions for loading data can lead to mismatches between the server-side and client-side HTML.

Resolving the Issue

To avoid the "Hydration completed but contains mismatches" error, you can use the following approaches:

  1. Client-Side Data Loading: Ensure that data is only loaded on the client after Vue components are initialized.
  2. Using Lifecycle Hooks: Use Vue lifecycle hooks to perform operations after component initialization.
  3. Removing State on Initialization: Remove the state on initialization and then restore it on the client.

Example code using lifecycle hooks:

// store/myStore.js
import { defineStore } from 'pinia';
import { useNuxtApp } from '#app';

export const useMyStore = defineStore('myStore', {
  state: () => ({
    items: ref([]),
    loading: ref(false),
    error: ref(null)
  }),
  actions: {
    async fetchItems() {
      if (this.items?.length > 0) {
        return;
      }
      this.loading = true;

      const $appConfig = useNuxtApp();
      const apiUrl = $appConfig.api?.url;

      try {
        const data = await $fetch(`${apiUrl}/reference-data/airports/`);
        this.items = data;
      } catch (err) {
        this.error = err;
      } finally {
        this.loading = false;
      }
    }
  },
  persist: {
    storage: piniaPluginPersistedstate.sessionStorage()
  }
});

// components/MyComponent.vue
<template>
  <div>
    <h1>My Component</h1>
    <button @click="fetchItems">Fetch Items</button>
    <ul v-if="!loading && items.length">
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
    <p v-if="loading">Loading...</p>
    <p v-if="error">{{ error.message }}</p>
  </div>
</template>

<script setup>
import { useMyStore } from '~/store/myStore';

const myStore = useMyStore();

const fetchItems = async () => {
  myStore.fetchItems();
};
</script>

Practical Tips

  1. Use Lifecycle Hooks: Ensure that data is loaded only after Vue components are initialized.
  2. Use Conditional Expressions: Use conditional expressions for loading data to avoid hydration errors.
  3. Separate Server and Client Code Logic: Ensure that server-side and client-side code logic aligns.

Conclusion

Loading data during the SSR phase using Pinia Store requires attention to detail. Utilizing lifecycle hooks and proper organization of logic can help prevent hydration errors and ensure your application works correctly.


SEO_TITLE

How to Load Data in SSR Using Pinia Store

SEO_DESCRIPTION

Learn how to correctly load data during the SSR phase using Pinia Store and avoid hydration errors.

SEO_KEYWORDS

Pinia Store, SSR, Vue.js, data loading, hydration errors

TAGS

Vue.js, Pinia, SSR, data loading, Vue components