DEV Community

Cover image for Persist data with Vue Pinia
Ezichi Ebere Ezichi
Ezichi Ebere Ezichi

Posted on

Persist data with Vue Pinia

Introduction

As a Software Developer who spends more time on the Backend, every now and then I try to do some things on the frontend occassionally. I wanted to explore Pinia and experience some of its features. In this post, I will share how I persisted data using Pinia and localStorage.

The App

To create the Vue 3 app, we run the command below and follow the prompt. Be sure to add Pinia for state management.

npm create vue@latest

You can run the commands to install dependencies and start the app.

cd project-name
npm install
npm run dev

Open the App with an editor(I use Vscode).

Create a file named authStore.js inside the src/stores folder. Add this code to the file.

import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useAuthStore = defineStore("auth", () => {
  const user = ref(null);

  const getUser = computed(() => user.value);

  const setUser = (newUser) => {
    user.value = newUser;
  };

  return {
    user,
    setUser,
    getUser,
  };
});

Enter fullscreen mode Exit fullscreen mode

We can now use the store values in our views. I had to clean up the default codes in the view files.

src/App.vue

<script setup>
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <header>
    <nav>
      <RouterLink to="/">Home</RouterLink>
      <RouterLink to="/about">About</RouterLink>
    </nav>
  </header>

  <RouterView />
</template>

<style scoped>
</style>
Enter fullscreen mode Exit fullscreen mode

src/Home.vue

<script setup>
import { ref } from 'vue';
import { useAuthStore } from '@/stores/authStore';

const authStore = useAuthStore();
const name = ref(null);

const login = () => {
  authStore.setUser(name.value);
};
</script>

<template>
  <main>
    <h1>Home</h1>
    <p v-if="authStore.user !== null">Welcome, {{ authStore.getUser }}</p>
    <div>
      <h3>Enter your name</h3>
      <form @submit.prevent="login">
        <input type="text" v-model="name">
        <button type="submit">Login</button>
      </form>
    </div>
  </main>
</template>
Enter fullscreen mode Exit fullscreen mode

src/About.vue

<script setup>
import { useAuthStore } from '@/stores/authStore';

const authStore = useAuthStore();
</script>
<template>
  <div class="about">
    <h1>This is an about page</h1>
    <p v-if="authStore.user !== null">Welcome, {{ authStore.getUser }}</p>
  </div>
</template>

<style>
</style>

Enter fullscreen mode Exit fullscreen mode

In the App.vue, I removed all the unnecessary codes. In the home and about, I mimicked a login and the user value was saved to the store. So, in a real login system we can have data from API and save it to the store and use across pages.

The Issue

If you notice, when the page is refreshed, the user value in the store resets to null. This is because Pinia stores are not persisted across refreshes.

The fix

There are different ways to fix this particular issue. I will use localstorage to solve this in the store. We have to make a few changes.

Update the login method in Home.vue. This stores the value in the localstorage.

const login = () => {
  authStore.setUser(name.value);
  localStorage.setItem('app_user', name.value);
};
Enter fullscreen mode Exit fullscreen mode

Update the authStore to load value from localstorage if the value exists.

import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useAuthStore = defineStore("auth", () => {
  const user = ref(null);

  if (localStorage.getItem("app_user")) {
    user.value = localStorage.getItem("app_user");
  }

  const getUser = computed(() => user.value);

  const setUser = (name) => {
    user.value = name;
  };

  return {
    user,
    setUser,
    getUser,
  };
});
Enter fullscreen mode Exit fullscreen mode

With these changes, even with page reload, the data persists! Be sure to drop comments, questions or suggestions.

Top comments (1)

Collapse
 
simbamkenya profile image
simbamkenya

Great work!