Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a created() for vuex actions to auto dispatch

I have an action within vuex that I would like to auto dispatch within vuex itself rather than a component.

I have created a notification bar that changes through different notifications which is on multiple pages. Rather than the notifications start from the beginning when I switch page I have created a store to set which notification to show.

I would like to dispatch the rotate function in the vuex store from within vuex rather than from within a component

Please note: I'm using Nuxt

VUEX State: store/notifications.js

export const state = () => ({
    section: 0,
    notifications: [
        'notification 1',
        'notification 2',
        'notification 3'
    ]
})

export const mutations = {
    INC_SECTION(state) {
        state.section ++
    },
    RESET_SECTION(state) {
        state.section = 0
    }
}

export const actions = {
    rotate({commit, dispatch, state}) {
            setTimeout(() => {
                
                let total = state.notifications.length -1
    
                if (state.section === total) {
                    commit('RESET_SECTION')
                }
                else {
                    commit('INC_SECTION')
                }
                dispatch('rotate')
    
            }, 3500)
    }
}

export default {
    state,
    mutations,
    actions
}

VUE JS Component:

<template>
  <section class="notifications">
    <template v-for="(notification, i) in notifications" >
      <p v-if="$store.state.notifications.section === i" :key="i">{{notification}}</p>
    </template>
  </section>
</template>

<script>
export default {
  data() {
    return { notifications: [] }
  },
  computed: {
    setData() {
      this.notifications = this.$store.state.notifications.notifications
    }
  },
  created() {
    this.setData
  }
}

</script>
like image 731
Nate Avatar asked Jan 22 '19 22:01

Nate


People also ask

How do I dispatch an action from action in Vuex?

You can call another Vuex action by passing the name of that action as a string as the first argument of dispatch : const store = new Vuex. Store({ actions: { walk(context) { context. dispatch("goForward"); }, goForward(context) { // }, }, });

Can Vuex actions be async?

An action in Vuex is where you perform interaction with APIs and commit mutations. Such interactions are inherently asynchronous.

Do Vuex actions return a promise?

In Vuex actions are asynchronous. If an action is complete , there is no way to detect that. You can return a Promise to let the calling function know that the action is complete. In the below example myAction returns a Promise.

What is the difference between actions and mutations Vuex?

Actions are similar to mutations, the differences being that: Instead of mutating the state, actions commit mutations. Actions can contain arbitrary asynchronous operations.


1 Answers

There are a lot of much cleaner ways you can do this.

First of all if you are using Nuxt, then, IMO you should be using its awesome feature of middlewares for dispatching actions (your use case of not keeping it, on the component level).

Secondly, Vuex provides us mapGetters functionality which makes the state properties available in the components while keeping them reactive, at the same time, too.

So, you can go with the following:

Vuex Store:

export const state = () => ({
  section: 0,
  notifications: ["notification 1", "notification 2", "notification 3"]
});

export const mutations = {
  INC_SECTION(state) {
    state.section++;
  },
  RESET_SECTION(state) {
    state.section = 0;
  }
};

export const actions = {
  rotate({ commit, dispatch, state }) {
    setTimeout(() => {
      let total = state.notifications.length - 1;
      if (state.section === total) {
        commit("RESET_SECTION");
      } else {
        commit("INC_SECTION");
      }
      dispatch("rotate");
    }, 3500);
  }
};

export const getters = {
  notifications(state) {
    return state.notifications;
  },
  section(state) {
    return state.section;
  }
};

export default {
  state,
  mutations,
  actions,
  getters
};

Vue Component:

<template>
  <section class="notifications">
    <template v-for="(notification, i) in notifications">
      <p v-if="section === i" :key="i">{{ notification }}</p>
    </template>
  </section>
</template>

<script>
import { mapGetters } from "vuex";
export default {
  data() {
    return {};
  },
  computed: {
    ...mapGetters(["notifications", "section"])
  }
};
</script>

Middleware

export default function({ store }) {
  store.dispatch("rotate");
}

depending on your use case, you can keep this middleware global (attached to routes), or attached to a specific layout.

here is a working sandbox example. hope this will help you out.

like image 114
waleed ali Avatar answered Oct 23 '22 02:10

waleed ali