Persist data with Vue Pinia

Rmag Breaking News

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,
};
});

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>

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 vif=authStore.user !== null>Welcome, {{ authStore.getUser }}</p>
<div>
<h3>Enter your name</h3>
<form @submit.prevent=login>
<input type=text vmodel=name>
<button type=submit>Login</button>
</form>
</div>
</main>
</template>

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 vif=authStore.user !== null>Welcome, {{ authStore.getUser }}</p>
</div>
</template>

<style>
</style>

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

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,
};
});

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

Leave a Reply

Your email address will not be published. Required fields are marked *