user984187
user984187

Reputation:

VUEJS 3 composition computed and vuex not reactive

I am trying to build website using vuejs3 with the composition api and I am using the VUEX 4 for state management.

Currently I am in the process of setting up the login functionality and it is working perfectly. The only thing not working is the reactivity of the computed property. Inside the navigation bar I have a computed property to change the login and register options to dashboard and logout.

This is my store module called "auth"

export default {
namespaced: true,
state: {
    token: false,
    user: false,
    is_Authenticated: false
},
getters: {
    is_Authenticated(state) {
        return state.token && state.user;
    },
    get_User(state) {
        return state.user;
    }
},

In my navbari have this.

<script>
import { ref, computed, defineComponent } from 'vue';
import { useStore } from 'vuex';
import { useRouter, useRoute } from 'vue-router'
import Menubar from 'primevue/menubar';

export default defineComponent({
  name: "Navbar",
  components: {
    Menubar
  },
  setup(){
    const store = useStore();
    const router = useRouter();

    const is_Authenticated = computed(() => store.getters['auth/is_Authenticated']);

When I log in, the values for "state.user" and "state.token" get filled with the corresponding data and the the getter, as far as my knowledge goes, should be returning true. And with that update the computed propperty. Then the navigation should be changing

I use the following in the navigation

{
  label: 'Account',
  icon: 'pi pi-user',
  items:[
    {
      label: 'Login',
      to: '/login',
      visible: !is_Authenticated
    },
    {
      label: 'Register',
      to: '/register',
      visible: !is_Authenticated
    },
    {
      label: 'Dashboard',
      to: '/dashboard',
      visible: is_Authenticated,
    },
    {
      label: 'Logout',
      visible: is_Authenticated,
      command: () => {
        store.dispatch('auth/logout')
        .then(() => {
          router.replace({
            name: 'Home'
          });
        })
      }
    },

Here is the navigation bar values. Small note: I use the PrimeVue component library

const items = ref([
  {
    label: 'Home',
    icon: 'pi pi-home',
    to: '/'
  },
  {
    label: 'Account',
    icon: 'pi pi-user',
    items:[
      {
        label: 'Login',
        to: '/login',
        visible: !is_Authenticated
      },
      {
        label: 'Register',
        to: '/register',
        visible: !is_Authenticated
      },
      {
        label: 'Dashboard',
        to: '/dashboard',
        visible: is_Authenticated,
      },
      {
        label: 'Logout',
        visible: is_Authenticated,
        command: () => {
          store.dispatch('auth/logout')
          .then(() => {
            router.replace({
              name: 'Home'
            });
          })

        }
      },
    ]
  }
]);

Now you would image when login in that the computed "is_Authenticated" would be true and everything would be great. But the computed doesn't update at all. there is no reactivity. The getter "is_Authenticated" also returns the state.user instead of a true or false.

I already tried to put use a state var called "is_Authenticated" and let the getter return that. In the VUE Dev Tools I changed the value of is_Authenticated from false to true and saw the getter being updated but the page wasn't. The computed getter just doesn't respond at all.

I am most likely doing stuff wrong as I am learning as I go. But hope someone has a solution to this. Thanks

Upvotes: 0

Views: 1649

Answers (1)

user984187
user984187

Reputation:

So going by the suggestion by Estus Flask I moved the menu item array to the store. Create a module called "navigation" This is the complete store.

import store from '../index';
import axios from 'axios';


export default {
    namespaced: true,
    state: {
        is_Authenticated: false,
        menu: [
            {
                label: 'Home',
                icon: 'pi pi-home',
                to: '/'
            },
            {
                label: 'Account',
                icon: 'pi pi-user',
                items:[
                    {
                        label: 'Login',
                        to: '/login',
                        visible: () => !store.getters['navigation/get_Authentication'],
                    },
                    {
                        label: 'Register',
                        to: '/register',
                        visible: () => !store.getters['navigation/get_Authentication'],
                    },
                    {
                        label: 'Dashboard',
                        to: '/dashboard',
                        visible: () => store.getters['navigation/get_Authentication'],
                    },
                    {
                        label: 'Logout',
                        visible: () => store.getters['navigation/get_Authentication'],
                        command: () => store.dispatch('navigation/logout'),
                    },
                ]
            }
        ],
    },
    getters: {
        get_Menu_Items(state) {
            return state.menu;
        },
        get_Authentication(){
            return store.getters['auth/is_Authenticated']
        }
    },
    mutations: {}
    },
    actions: {
        async logout({commit, dispatch}, needsAuthentication) {
            store.dispatch('auth/logout')
                .catch((e)=>{
                    console.log(e);
               });
        }
    },
}

I know that might be a better way if doing it but it works really well. Also found in the "auth" module the check to return true of the user and token are set should have 2 exclamation marks.

The getter code is now:

is_Authenticated(state) {
    return !!(state.user && state.token);
},

and now from the Navbar component I call

const items = computed( () => store.getters['navigation/get_Menu_Items']);

thanks again for the suggestion. Took me a while to get this worken. Hope it does now ^_^

Upvotes: 1

Related Questions