Search code examples
laravelvue.jsaxiospinia

How to fix Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'status') at app.js


I had the following code and everything was working as expected.

<template>
  <div id="login">
    <form @submit.prevent="submit">
      <p class="loading" :class="{ hideLoad: !loading }">Loading...</p>
      <label for="email">Email</label>
      <input type="text" id="email" v-model="fields.email" />
      <span v-if="errors && errors.email" class="error">{{
        errors.email[0]
      }}</span>

      <label for="password">Password</label>
      <input type="password" id="password" v-model="fields.password" />
      <span v-if="errors && errors.password" class="error">{{
        errors.password[0]
      }}</span>
      <button type="submit">Log In</button>
      <span
        >Don't have an account?
        <router-link :to="{ name: 'Register' }">Sign Up</router-link></span
      >
    </form>
  </div>
</template>


<script>
export default {
  data() {
    return {
      fields: {},
      errors: {},
      loading: false,
    };
  },
  methods: {
    submit() {
      this.loading = true;
      axios
        .post("/api/login", this.fields)
        .then((res) => {
          if (res.status == 201) {
            localStorage.setItem("authenticated", "true");
            this.$router.push({ name: "Dashboard" });
          }
        })
        .catch((error) => {
          if (error.response.status == 422) {
            this.errors = error.response.data.errors;
            this.loading = false;
          }
        });
    },
  },
};
</script> 

I then decided to use pinia to manage state and came up with the following.

<template>
  <div id="login">
    <form @submit.prevent="loginStore.submit">
      <p class="loading" :class="{ hideLoad: !loginStore.loading }">Loading...</p>
      <label for="email">Email</label>
      <input type="text" id="email" v-model="loginStore.fields.email" />
      <span v-if="loginStore.errors && loginStore.errors.email" class="error">{{
        loginStore.errors.email[0]
      }}</span>

      <label for="password">Password</label>
      <input type="password" id="password" v-model="loginStore.fields.password" />
      <span v-if="loginStore.errors && loginStore.errors.password" class="error">{{
        loginStore.errors.password[0]
      }}</span>
      <button type="submit">Log In 2</button>
      <span
        >Don't have an account?
        <router-link :to="{ name: 'Register' }">Sign Up</router-link></span
      >
    </form>
  </div>
</template>


<script setup>
import {useLoginStore} from '../stores/login'
const loginStore = useLoginStore();
</script> 

My login.js

import { defineStore } from 'pinia'

export const useLoginStore = defineStore('login', {
    state: () => {
        return {
            fields: {},
            errors: {},
            loading: false,
        }
    },

    actions: {
        submit() {
            this.loading = true;
            axios
              .post("/api/login", this.fields)
              .then((res) => {
                if (res.status == 201) {
                  localStorage.setItem("authenticated", "true");
                  this.$router.push({ name: "Dashboard" });
                }
              })
              .catch((error) => {
                if (error.response.status == 422) {
                  this.errors = error.response.data.errors;
                  this.loading = false;
                }
              });
          },
    },

})

Everything is working as before and the only error is that when I fill the form with the correct credential and submit then I get Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'status') at app.js

I've tried all I can and I just can't figure out what it is that I'm doing wrong.


Solution

  • After debugging it further, I realized the error was coming from this.$routerinstance since a user gets login successfully and the status code is okay when I console log.

    The instance is available in components only https://router.vuejs.org/api/#component-injected-properties

    So, I fixed the problem by importing router in the store.js file,

    import router from '../router'
    

    then I pushed to another route by just using

    router.push({ name: "Dashboard" });

    instead of this.$router.push({ name: "Dashboard" });