Search code examples
javascriptvuexactiondispatchpinia

How can I apply globally to Pinia state actions?


How can I apply globally to Pinia state actions. I know how to send data (user) as an attribute to Vuex. But how can I do something similar with Pinia. As well as is there a way do accomplish similar issue with Vue-router globally ?

    methods: {
      submit(event: any) {
        event.preventDefault();
        let user = {
          firstName: this.firstName,
          lastName: this.lastName,
        }

        this.$store.dispatch('login', user)  // rewrite this line to Pinia
        this.$router.push('/');              // rewrite this line to Pinia

        this.firstName = '';
        this.lastName = '';
      }
    }


Solution

  • Assuming that you wanted to implement login logic with pinia, here is a basic sample how you can achieve it:

    stores/user.js

    import { defineStore } from "pinia";
    export const useStore = defineStore("user", {
      state: () => ({
        user: null
      }),
      actions: {
        login(user) {
          this.user = user;
        }
      }
    });
    

    Home.vue

    <template>
      <h1>home</h1>
      <h2 v-if="user">Hello, {{ user.firstName }} {{ user.lastName }}</h2>
    </template>
    
    <script setup lang="ts">
    import { computed } from "vue";
    import { useStore } from "@/stores/user";
    
    const store = useStore();
    
    const user = computed(() => {
      return store.user;
    });
    </script>
    

    Login.vue

    <template>
      <div>
        <form @submit.prevent="submit">
          <input type="text" id="firstName" v-model="firstName" />
          <input type="text" id="lastName" v-model="lastName" />
          <button type="submit">Submit</button>
        </form>
      </div>
    </template>
    
    
    <script setup lang="ts">
    import { ref } from "vue";
    import { useStore } from "@/stores/user";
    import { useRouter } from "vue-router";
    
    const firstName = ref("");
    const lastName = ref("");
    const store = useStore();
    const router = useRouter();
    
    const submit = () => {
      let user = {
        firstName: firstName.value,
        lastName: lastName.value,
      };
    
      store.login(user);
      router.push("/");
    };
    </script>
    

    In router.js you can add guards to redirect login page if user is not authenticated:

    import { createRouter, createWebHistory } from "vue-router";
    import Home from "@/views/Home.vue";
    import Login from "@/views/Login.vue";
    import { useStore } from "@/stores/user";
    const routes = [
      {
        path: "/",
        name: "Home",
        component: Home
      },
      {
        path: "/login",
        name: "Login",
        component: Login
      }
    ];
    
    const router = createRouter({
      history: createWebHistory("/"),
      routes
    });
    
    router.beforeEach((to, from, next) => {
      const store = useStore();
      const isAuthenticated = store.user !== null;
    
      if (to.name !== "Login" && !isAuthenticated) {
        next({ name: "Login" });
      } else {
        next();
      }
    });
    
    export default router;