Logo

dev-resources.site

for different kinds of informations.

Pinia and Nuxt 3

Published at
1/3/2023
Categories
nuxt3
nuxt
pinia
vue
Author
rafaelmagalhaes
Categories
4 categories in total
nuxt3
open
nuxt
open
pinia
open
vue
open
Author
15 person written this
rafaelmagalhaes
open
Pinia and Nuxt 3

Pinia is now the recommended choice by Vue and is now an official part of the whole Vue ecosystem, maintained and developed by core members of the Vue team

 

Creating a new project

 


 bash
npx nuxi init nuxt3-pinia


Enter fullscreen mode Exit fullscreen mode

Install pinia



npm i @pinia/nuxt pinia -D


Enter fullscreen mode Exit fullscreen mode

add module to nuxt.config.ts



export default defineNuxtConfig({
  modules: [
    // ...
    '@pinia/nuxt',
  ],
});


Enter fullscreen mode Exit fullscreen mode

Creating a todo store

create store folder in root of project, then create a todos.ts file, we will be calling https://jsonplaceholder.typicode.com/todos this is a mock API which returns a list of todos

Before diving into core concepts, we need to know that a store is defined using defineStore() and that it requires a unique name, passed as the first argument:

store/todos.ts



import { defineStore } from 'pinia';
export const useTodosStore = defineStore('todos', {

});


Enter fullscreen mode Exit fullscreen mode

In Pinia the state is defined as a function that returns the initial state. This allows Pinia to work in both Server and Client Side.

let's create an empty todos state

store/todos.ts



  state: () => ({
    todos: [],
  }),


Enter fullscreen mode Exit fullscreen mode

Now lets create an action, which will call the endpoint above to fetch a list of todos and assign the data to the todos state

Actions are the equivalent of methods in components. They can be defined with the actions property in defineStore() and they are perfect to define business logic:

store/todos.ts



  async fetchTodos() {
      const { data } = await useFetch('https://jsonplaceholder.typicode.com/todos'); 
      if (data.value) {
        this.todos = data.value;
      }
  }


Enter fullscreen mode Exit fullscreen mode

Nuxt 3 provides new composable called useFetch this will let us do a GET call without having to install axios

the completed code now for store/todos.ts



import { defineStore } from 'pinia';

export const useTodosStore = defineStore('todos', {
  state: () => ({
    todos: [],
  }),
  actions: {
    async fetchTodos() {
      const { data }: any = await useFetch('https://jsonplaceholder.typicode.com/todos');
      if (data.value) {
        this.todos = data.value;
      }
    },
  },
});


Enter fullscreen mode Exit fullscreen mode

How to use the todos store

open app.vue we now need to import our fetchTodos function from the store



import { useTodosStore } from '~/store/todos';


Enter fullscreen mode Exit fullscreen mode

now we need to destructure our store and call the actions, states we need, destructuring the store will break reactivity.



const { fetchTodos, todos } = useTodosStore();


Enter fullscreen mode Exit fullscreen mode

to maintain the reactivity we can use a computed property or storeToRefs()

Reactivity with computed

use computed property to make todos state reactive



const store = useTodosStore();

const todos =  computed(() => store.todos)


Enter fullscreen mode Exit fullscreen mode

Reactivity with storeToRefs()

storeToRefs() lets us destructure the store value while keeping it reactive



import { storeToRefs } from 'pinia'

const store = useTodosStore();
const { todos,} = storeToRefs(store)



Enter fullscreen mode Exit fullscreen mode

what about functions

storeToRefs doesn't allow us to destructure a function we can simply call an action with store.fetchTodos or we can destructrutre the store value



import { storeToRefs } from 'pinia'

const store = useTodosStore();
const { fetchTodos } = store; // have all non reactiave stuff here 
const { todos } = storeToRefs(store) // have all reactive states here


Enter fullscreen mode Exit fullscreen mode

because Nuxt 3 supports top level async/await we can just call fetchTodos action



await fetchTodos();


Enter fullscreen mode Exit fullscreen mode

now on our html can we loop over the todos and display each one



<template>
  <div>
    <h1>Todos:</h1>
    <ul v-for="todo in todos" :key="todo.id">
      <li>{{ todo.title }}</li>
    </ul>
  </div>
</template>


Enter fullscreen mode Exit fullscreen mode

now we should see a list of todos

complete code for app.vue



<template>
  <div>
    <h1>Todos:</h1>
    <ul v-for="todo in todos" :key="todo.id">
      <li>{{ todo.title }}</li>
    </ul>
  </div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia';
import { useTodosStore } from '~/store/todos';

const store = useTodosStore();
const { fetchTodos } = store; // have all non reactiave stuff here
const { todos } = storeToRefs(store); // have all reactive states here

await fetchTodos();
</script>


Enter fullscreen mode Exit fullscreen mode

Alternative away of setting up pinia store




import { defineStore } from 'pinia';

export const useTodosStore = defineStore('todos', () => {
  const todos = ref([]);  // ref by defaults are states,

 // functions get added to actions

  const fetchTodos = async () => { 
    const { data }: any = await useFetch('https://jsonplaceholder.typicode.com/todos');
    if (data.value) {
      todos.value = data.value;
    }
  };

// we must return what we want to use accross the application
  return {
    todos,
    fetchTodos,
  };
});



Enter fullscreen mode Exit fullscreen mode

This way of setting up the store feels very familiar way of creating a composbale in vue

You can find the repository here

nuxt3 Article's
30 articles in total
Favicon
Renderización Dinámica de Componentes en Vue 3 y Nuxt 3: Guía Práctica y Caso Real
Favicon
Nuxt3 CSR Background Image Lazy loading
Favicon
DartsMash: a platform for darts enthusiasts
Favicon
Nuxt3 : limitation on Layers & Modules
Favicon
Using postgresql with nuxt3 by ORM(sequelize)
Favicon
Nuxt3 : API error handling
Favicon
Nuxt Icon
Favicon
Integrating Nuxt 3 with Recaptcha v3 for Token Handling 🤖🔐
Favicon
Nuxt 3 Starter
Favicon
Nuxt 3 Builder: A Tailored Editor for Developers
Favicon
Build an X clone w/ Nuxt UI
Favicon
Nuxt3 Form with Feedback
Favicon
Custom 404 Page in Nuxt
Favicon
Nuxt 3 authentication with pinia
Favicon
Nuxt 3, UnoCSS, and Preset rem to px
Favicon
Configuração e instalação do Nuxt 3
Favicon
The DevOnly component in Nuxt 3: A developer's best friend
Favicon
Storyblok Nuxt 3 news 🗞
Favicon
Implementing OpenID Connect (OIDC) Authentication with Nuxt 3
Favicon
Authentication in Nuxt 3
Favicon
Adding ESLint and Prettier to Nuxt 3 ✨ (2024)
Favicon
API Management in Nuxt 3 with TypeScript
Favicon
Docker and Nuxt 3
Favicon
Pinia and Nuxt 3
Favicon
Adding Pinia to Nuxt 3 🍍 (2023)
Favicon
Adding Vitest to Nuxt 3 ⚡ (2023)
Favicon
Adding Tailwind CSS to Nuxt 3 🍃 (2023)
Favicon
How I set up eslint in my projects
Favicon
How to create and minify Vuetify 3 Nuxt 3 project bundle
Favicon
Build an Intercom clone in Nuxt.js - Part Two

Featured ones: