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 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>
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>
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.
Top comments (1)
Great work!