Robin Fermaud

Robin Fermaud

Pinia - The new flexible store library for VueJs

What is Pinia, the new recommended store library for VueJs? What are the advantages compared to Vuex?


pinia-vuex-state-management

What is Pinia?#

Pinia is a state management plugin that is used with VueJs. Since Vue 3, it is now recommended to use Pinia instead of Vuex. It has been made to be simple while offering great flexibility and power. It can be used in two ways: options store (quite similar to Vuex) or setup store (composition api). If you are familiar with Vuex you will find Pinia really easy to use. Pinia also supports HMR (Hot Module Replacement) and devtools.

Pinia & composition API#

If you like to use composition API you will be able to design your store with it. The defineStore(storeId, store) function takes 2 arguments: storeId and a store (Option or Setup).

// With Options API (almost similar to Vuex)
const useAuthStore = defineStore('auth', {
  state: () => ({ firstName: '', lastName: '' }),
  getters: {
    fullName: (state) => `${state.firstName} ${state.lastName}`,
  },
  actions: {
    // Here no more { state, commit, dispatch, rootState } first arg you can call any other action or getters by importing it
    loginUser(email: string, pwd: string) {
      const { data } = await api().post({ email, pwd });
      this.firstName = data.firstName;
      this.lastName = data.lastName;
    },
  },
})
// With composition API
const useAuthStore = defineStore('auth', () => {
  const firstName = ref<string>('');
  const lastName = ref<string>('');

  const fullName = computed(() => `${state.firstName} ${state.lastName}`)

  const loginUser = (email: string, pwd: string) {
    const { data } = await api().post({ email, pwd });
    firstName.value = data.firstName;
    lastName.value = data.lastName;
  }

  // Here you can return only what you want to expose
  return { fullName, loginUser }
})

Pinia vs Vuex#

  • Simpler api, less syntax to learn (perfect for beginners who want to start building a complex front-end application).
  • Pinia supports option (easier if you migrate your app from Vuex) & composition API
  • Pinia gets rid of mutations and magic string to call actions. (less verbosity).
// Call action with Vuex, it was too easy to make a typo
// No TypeScript autocompletion here because it's just a magic string
dispatch('auth/loginUser', {
  email: 'jimmy@jones.com',
  password: '123456'
}, { root: true }); // to call action from another store
  • With Pinia you can write directly in the store without calling mutations with commit.
import { useLoginStore } from '@/store/modules';

// TS autocompletion
useLoginStore().loginUser({
  email: 'jimmy@jones.com',
  password: '123456'
});
  • With Pinia, you can call stores anywhere in the app, it even allows you to have circular dependencies (stores can be call each other). So you should not use nested stores anymore.
  • With createPinia function you can create reusable plugins.
  • Pinia provides tools (like @pinia/testing) to help you test your front-end application. You can mock actions, store and getters easily (this is a work in progress, so the computing mocking may not work at this time).

Our experience with Pinia#

At 365Talents, since a few months, we are working on a migration from VueX to Pinia. Due to the size of the application and its evolution we could not do this migration in one big PR, so we had to make Vuex and Pinia cohabit. Our strategy was to migrate the stores one by one, starting with those that had the least dependencies. During the migration, we took the opportunity to migrate them to typescript, to improve the global typing of the application.

If you're using options api, Pinia provides some helpers like mapState (equivalent of mapGetters) or mapActions to replace those used by vuex.

// Vuex
...mapActions('auth' , 'loginUser'),

// Pinia
...mapActions(useAuthStore, 'loginUser')
// Vuex
...mapGetters('auth' , 'fullName'),

// Pinia
...mapState(useAuthStore, 'loginUser')

If you're using composition api you can access your getters or state using storeToRefs() function.

const { fullName } = storeToRefs(useAuthStore());

// it's a ref, to access the value don't forget to add .value
console.log(fullName.value);

Conclusion#

If you're using Vuex, don't worry, Pinia is just a new way to create and manage store in VueJs. For the moment Vuex is not intended to be deprecated. You should rather see Pinia as the version 5 of Vuex. Easy to use, modular, flexible, extremely light. If you're about to start a project in Vuejs, Pinia is probably the best choice for your state management. If you are using the composition api you will be able to have a similar design between your components and your stores. Our last step is now the migration from VueX ORM to Pinia ORM.