Why is my Vue/Vuex subscriber not firing?

367 Views Asked by At

I have set up my Vuex subscribe function to store user auth in localStorage and I can't figure out for the life of me why the subscriber isn't firing at all. I can't even get a console.log() from it. Here is the relevant content from my project.

main.js

import Vue from 'vue';
import Buefy from 'buefy';
import axios from 'axios';
import router from '@/router';
import store from '@/store';
import App from './App.vue';
import 'buefy/dist/buefy.css';
import '@/store/subscriber';

Vue.config.productionTip = false;

Vue.use(Buefy);

Vue.prototype.$http = axios;
const token = localStorage.getItem('x-auth-token');
if (token) Vue.prototype.$http.defaults.headers.common['x-auth-token'] = token;
Vue.prototype.$http.defaults.baseURL = 'http://localhost:5000/v1/';

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

store/index.js

import Vue from 'vue';
import Vuex from 'vuex';
import auth from './auth';
import transactions from './transactions';

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    auth,
    transactions,
  },
});

store/subscriber.js

import Vue from 'vue';
import store from '@/store';

store.subscribe = (mutation) => {
  console.log(mutation);
  console.log("WHY AREN'T YOU WORKING!!!???");

  switch (mutation.type) {
    case 'auth/SET_TOKEN':
      if (mutation.payload) {
        Vue.prototype.$http.defaults.headers.common['x-auth-token'] = mutation.payload;
        localStorage.setItem('x-auth-token', mutation.payload);
      } else {
        Vue.prototype.$http.defaults.headers.common['x-auth-token'] = '';
        localStorage.removeItem('x-auth-token');
      }
      break;
    case 'auth/SET_USER':
      if (mutation.payload) {
        Vue.prototype.$http.defaults.headers.common.user = JSON.stringify(mutation.payload);
        localStorage.setItem('user', JSON.stringify(mutation.payload));
      } else {
        Vue.prototype.$http.defaults.headers.common.user = '';
        localStorage.removeItem('user');
      }
      break;
    default:
      Vue.prototype.$http.defaults.headers.common['x-auth-token'] = '';
      Vue.prototype.$http.defaults.headers.common.user = '';
  }
};

store/auth.js

import axios from 'axios';

export default {
  namespaced: true,
  state: {
    token: localStorage.getItem('x-auth-token') || '',
    user: {},
  },
  getters: {
    authenticated(state) {
      return state.token && state.user;
    },
    user(state) {
      return state.user;
    },
  },
  mutations: {
    SET_TOKEN(state, token) {
      state.token = token;
    },
    SET_USER(state, data) {
      state.user = data;
    },
  },
  actions: {
    async signIn({ commit, dispatch }, credentials) {
      try {
        const { data } = await axios.post('users/login', credentials);
        const { token, user } = data;
        if (token) {
          commit('SET_TOKEN', token);
        }
        commit('SET_USER', user);
        return data;
      } catch (err) {
        dispatch('signOut');
        return err.response;
      }
    },
    async registerUser({ commit, dispatch }, credentials) {
      try {
        const { data } = await axios.post('users/register', credentials);
        const { token, user } = data;
        if (token) {
          commit('SET_TOKEN', token);
        }
        commit('SET_USER', user);

        return data;
      } catch (err) {
        dispatch('signOut');
        return err.response;
      }
    },
    signOut({ commit }) {
      commit('SET_TOKEN', '');
      commit('SET_USER', {});
    },
  },
};

views/LogIn.vue

<template>
  <div>
    <h1 class="title has-text-centered is-size-1 mt-6">Log In</h1>
    <div class="box column is-half is-offset-one-quarter mt-6 px-6">
      <form @submit.prevent="handleSubmit" action="GET" class="my-5">
        <b-field label="Username" for="username" :type="usernameValidation">
          <b-input v-model="user.username" id="username" name="username" placeholder="Username"></b-input>
        </b-field>
        <b-field
          label="Password"
          for="password"
          :type="passwordValidation"
          :message="passwordMessage"
        >
          <b-input
            v-model="user.password"
            type="password"
            id="password"
            name="password"
            placeholder="Password"
            password-reveal
          ></b-input>
        </b-field>
        <div class="buttons is-centered">
          <b-button native-type="submit" class="is-success mt-5 mb-4 has-text-weight-bold">Log In</b-button>
        </div>
        <div class="level">
          <div class="level-left">
            <router-link class="level-item" to="/signup">Sign Up</router-link>
          </div>
          <div class="level-right">
            <router-link class="level-item" to="/forgotpassword">Forgot Password</router-link>
          </div>
        </div>
      </form>
    </div>
  </div>
</template>
<script>
import { mapActions } from 'vuex';

export default {
  name: 'LogIn',
  data: () => ({
    user: {
      username: '',
      password: '',
    },
    usernameValidation: '',
    passwordValidation: '',
    passwordMessage: '',
  }),
  methods: {
    ...mapActions({
      signIn: 'auth/signIn',
    }),
    async handleSubmit() {
      const { data } = await this.signIn(this.user);
      if (data) {
        this.usernameValidation = 'is-danger';
        this.passwordValidation = 'is-danger';
        this.passwordMessage = data.message;
      } else {
        this.$router.push('/');
      }
    },
  },
};
</script>
1

There are 1 best solutions below

1
On

You are totally going to kick yourself.

Two problems

  1. You weren't including the subscribe.js file so your subscriber was never being subscribed. You've since imported this in main.js which solves that issue.
  2. store.subscribe() is a function you are meant to call, providing a subscriber function but you are assigning it a new function. Try this instead
store.subscribe((mutation) => {
  console.log(mutation);
  console.log("OMG YOU'RE WORKING!!!");

  // etc
})

Edit goofy-architecture-pknzm