---
title: How to Get Started with Pinia in Vue
description: Pinia, the lightweight state management library, and Vue make a great team! Get started using Pinia in Vue with this quick tutorial.
image: https://www.bitovi.com/hubfs/How%20to%20Get%20Started%20with%20Pinia%20in%20Vue.png
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting)
- ![Project Management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project Management](https://www.bitovi.com/services/agile-project-management-consulting)
- ![Product Design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product Design](https://www.bitovi.com/services/product-design-consulting)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting)
- [Design systems](https://www.bitovi.com/services/axure-figma-migration)
- [React](https://www.bitovi.com/services/frontend/react-consulting)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about delivering products and solving problems.
  
  ](https://www.bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships)
- [![Academy](https://www.bitovi.com/hubfs/icon%20-%20academy%20(4).svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse or contribute to our community
  
  ](https://www.bitovi.com/open-source)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

 September 15, 2022

# How to Get Started with Pinia in Vue

 Pinia, the lightweight state management library, and Vue make a great team! Get started using Pinia in Vue with this quick tutorial.

![Eduard Krivanek](https://www.bitovi.com/hubfs/me_small.jpeg)

 Eduard Krivanek

Share:

[![Twitter](https://www.bitovi.com/hubfs/limbo-generated/_astro/twitter-white.os3xLc3C_Z2nW4or.svg) ](https://twitter.com/intent/tweet?text=) [![Reddit](https://www.bitovi.com/hubfs/limbo-generated/imgs/icons/reddit.png) ](http://reddit.com/submit?url=)

You are starting your VueJs project and you get stuck on a question: how am I going to share data across multiple components? While there are a variety of lightweight state management libraries for Vue, [Pinia](https://pinia.vuejs.org/introduction.html) is the one [officially recommended by the Vue team](https://vuejs.org/guide/scaling-up/state-management.html#pinia), that solves sharing data across components intuitively.

On one hand, the most used library in Vue is [Vuex](https://vuex.vuejs.org/); however, Pinia has almost the exact same or enhanced API as Vuex 5, described in [Vuex 5 RFC](https://github.com/vuejs/rfcs/pull/271). Pinia can be considered as a successor of Vuex with a different name and is also compatible with Vue 2.x.

## Why Pinia?

Pinia has solid type inference support when used with TypeScript and provides a simpler API that led it to become the new recommended state management library by Vue. Looking at the [NPM download](https://www.npmjs.com/package/pinia) and the almost 9K stars on the [Pinia Github repo](https://github.com/vuejs/pinia#readme), Pinia is gaining popularity.

Comparison, such as [Pinia against Vuex](https://npmtrends.com/pinia-vs-vuex), shows that Vuex, the previously recommended library, still has a higher download rate than Pinia. However, even the [Vuex official documentation ](https://vuex.vuejs.org/)advises developers to opt-in for Pinia, since it is unlikely that Vuex will receive any additional functionalities.

## How to Install Pinia

Let’s take a look at how Pinia works. Installing and opting for Pinia is relatively straightforward. Follow the example below:

```
npm install pinia
```

```
// main.js or main.ts

import { createPinia } from "pinia";
import { createApp } from "vue";
import App from "./App.vue";

createApp(App)
.use(createPinia())
.mount('#app')
```

## How Storage Works

Pinia’s approach to handling global storage is based on modularity. We create multiple smaller stores, as it makes sense for our application, give them a unique identification key and in the end, Pinia combines each store into a single one. A store definition consists of four properties:

- **id** - a unique key that identifies part of the application state
- **state** - function that returns an initial state
- **getters** - a place to define compute values for the state of the Store
- **actions** - a place to define methods for mutation of the Store

```
import { defineStore } from "pinia";

export const useTodoStore = defineStore({
  id: "uniqueID",
  state: () => ({
    // ...
  }),
  getters: {
    // ...
  },
  actions: {
    // ...
  },
});
```

Pinia is also supported in [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=en), where, as mentioned before, the global `state` object is composed of multiple modular `defineStore({...})` objects with a unique key.

![pinia root](https://www.bitovi.com/hs-fs/hubfs/pinia%20root.png?width=694&name=pinia%20root.png)

## Example Application

Let’s create a todo application, consisting of the following steps:

1. Creating a `Todo` item form in `TodoForm.vue`
2. Persisting a newly created `Todo` in the global store
3. Displaying a list of `Todo` items from the global store in `TodoList.vue`

The whole source code can be found in the following [GitHub repository](https://github.com/krivanek06/example_projects/tree/main/vue-pinia-getting-started) and the end result is shown in the provided gif.

![pinia vue todo app](https://www.bitovi.com/hs-fs/hubfs/pinia%20vue%20todo%20app.gif?width=600&name=pinia%20vue%20todo%20app.gif)

By using TypeScript, first, you create an interface representing your `Todo` items.

```
// types/todo.ts

export interface ITodo {
  id: number;
  title: string;
  description?: string;
}
```

### Setting Up State Storage

Representation of our Todo storage is shown in the following snippet.

In the `action` section, you implement two mutation methods that will update the store state. The first one is `addTodo`, which adds a new `Todo` item to the list of todos, and the second one is `removeTodo`, which removes one by its `Id`. Mutations can access the store state by using the keyword `this`, so in your case, you access todos by `this.todos`.

It is also worth highlighting the `removeTodo` method to see that asynchronous mutations are performed in the same way as synchronous ones like the `addTodo` method in your case.

```
// store/todo.ts

import type { ITodo } from "@/types/todo";
import axios from "axios";
import { defineStore } from "pinia";

export const useTodoStore = defineStore({
  id: "todoState",
  state: () => ({
    todos: [] as ITodo[],
  }),
  getters: {
    totalTodos: (state) => state.todos.length,
  },
  actions: {
    addTodo(title: string, description?: string) {
      const todo: ITodo = {
        id: Math.floor(Math.random() * 10000), // random ID
        title,
        description,
      };
      this.todos = [todo, ...this.todos];
    },

    async removeTodo(id: number) {
      // example of an async request
      const response = await axios.get(
        "https://www.random.org/integers/?num=1&min=1&max=100&col=5&base=10&format=plain",
      );
      console.log("received data ", response.data);

      // remove todos
      this.todos = this.todos.filter((todo) => todo.id !== id);
    },
  },
});
```

### Display Todos

Both components `TodoForm.vue` and `TodoList.vue` are basic Vue components. The main concept of both of them is the [setup()](https://vuejs.org/api/composition-api-setup.html#basic-usage) method, which serves as an entry point to the component, where we store the reference to the todo store by `const storeTodo = useTodoStore()` so that it becomes available for the whole component.

```
// components/TodoForm.vue

<template>
  <form @submit="onSubmit">
    <h2>Todo Form</h2>

    <!-- title -->
    <div class="field">
      <label class="label">Title</label>
      <input type="text" class="input" name="title" v-model="title" />
    </div>

    <!-- description -->
    <div class="field">
      <label class="label">Description</label>
      <textarea class="input" name="description" v-model="description"></textarea>
    </div>

    <!-- submit -->
    <div class="field">
      <button type="submit">Create Todo</button>
    </div>
  </form>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { useTodoStore } from "../stores/todo";

export default defineComponent({
  name: "TodoForm",
  data() {
    return {
      title: "",
      description: "",
    };
  },
  setup() {
    const storeTodo = useTodoStore();
    return { storeTodo };
  },
  methods: {
    onSubmit(e: Event) {
      e.preventDefault();

      if (!this.title) {
        return;
      }

      // save data into store
      this.storeTodo.addTodo(this.title, this.description);
    },
  },
});
</script>

<style scoped>
/* ... */
</style>
```

```
// components/TodoList.vue

<template>
  <div>
    <div v-for="todo of storeTodo.todos" :key="todo.id" class="wrapper">
      <div class="header">
        <div class="title">[{{ todo.id }}] {{ todo.title }}</div>
        <div>
          <button type="button" @click="storeTodo.removeTodo(todo.id)">
            remove
          </button>
        </div>
      </div>
      <div v-if="todo?.description">{{ todo?.description }}</div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { useTodoStore } from "../stores/todo";

export default defineComponent({
  name: "TodoList",
  setup() {
    const storeTodo = useTodoStore();

    return { storeTodo };
  },
});
</script>

<style>
/* ... */
</style>
```

## Summary

Even as a lightweight state management library, Pinia has become the recommended library both by Vue and Vuex developers and it is maintained by the core Vue team.

We took a look at how to write and read data from storage by a basic `Todo` application. Pinia can be used for both Vue 2 and Vue 3 users and from small to large-scale applications. Need help with state management or setting up Pinia for Vue? Book a session for [Vue Consulting](https://www.bitovi.com/frontend-javascript-consulting/vue-consulting) or check out our training program [Bitovi Academy](https://www.bitovi.com/academy/).

### Do you have thoughts?

We’d love to hear them! Join our [Community Discord](https://discord.gg/J7ejFsZnJ4) to continue the conversation.

[![Tag for vue](https://www.bitovi.com/hubfs/limbo/icons/tag.svg) vue ](https://www.bitovi.com/blog/topic/vue)

 Previous Post

![Supercharge Your Angular Content Projection with ng-template](https://www.bitovi.com/hs-fs/hubfs/Supercharge%20Your%20Angular%20Content%20Projection%20with%20ng-template.png?height=117&name=Supercharge%20Your%20Angular%20Content%20Projection%20with%20ng-template.png) [ Supercharge Your Angular Content Projection with ng-template ](https://www.bitovi.com/blog/supercharged-content-projection-with-ng-template)

  

 Next Post

![Backend Basics: Anatomy of a Node API](https://www.bitovi.com/hs-fs/hubfs/Backend%20Basics-%20Anatomy%20of%20a%20Node%20API.png?height=117&name=Backend%20Basics-%20Anatomy%20of%20a%20Node%20API.png) [ Backend Basics: Anatomy of a Node API ](https://www.bitovi.com/blog/backend-basics-anatomy-of-a-node-api)

```json
{
  "@context" : "http://schema.org",
  "@type" : "Organization",
  "address" : {
    "@type" : "PostalAddress",
    "addressCountry" : "United States",
    "addressLocality" : "Libertyville",
    "addressRegion" : "IL",
    "postalCode" : "60048",
    "streetAddress" : "1134 Pine Tree Lane "
  },
  "alternateName" : "Bitovi",
  "areaServed" : {
    "@type" : "GeoCircle",
    "geoMidpoint" : {
      "@type" : "GeoCoordinates",
      "latitude" : "41.8781",
      "longitude" : "87.6298"
    },
    "geoRadius" : "5000 km"
  },
  "description" : "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
  "email" : "contact@bitovi.com",
  "image" : "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
  "logo" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
  "mainEntityOfPage" : {
    "@id" : "https://www.bitovi.com/blog/how-to-get-started-with-pinia-in-vue",
    "@type" : "WebPage",
    "description" : "Pinia, the lightweight state management library, and Vue make a great team! Get started using Pinia in Vue with this quick tutorial. "
  },
  "naics" : "541511",
  "name" : "Bitovi Web App Consulting",
  "sameAs" : [ "https://www.facebook.com/BitoviLLC/", "https://twitter.com/bitovi", "https://www.linkedin.com/company/bitovi" ],
  "telephone" : "312-620-0386",
  "url" : "http://bitovi.com"
}
```

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Eduard Krivanek"
  },
  "dateModified" : "October 6, 2023, 7:07:34 PM",
  "datePublished" : "2022-09-15 21:43:22",
  "description" : "Pinia, the lightweight state management library, and Vue make a great team! Get started using Pinia in Vue with this quick tutorial. ",
  "headline" : "How to Get Started with Pinia in Vue",
  "image" : {
    "@type" : "ImageObject",
    "url" : "https://www.bitovi.com/hubfs/How%20to%20Get%20Started%20with%20Pinia%20in%20Vue.png"
  },
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "url" : "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg"
    },
    "name" : "Bitovi"
  }
}
```