Best Practices for Sequencing Vuex Actions and Safely Updating the State in between Calls

I have a Vuex store set up in my application with defined getters, actions, and mutations. One of the actions, called initConfiguration, is responsible for fetching data from an API and then committing this data to a mutation that updates the state. This action is crucial as it loads essential metadata and configurations required by other actions in the store. In my main component, I have included some initialization code within the mounted lifecycle hook:

new Vue({
  el: '#app',
  store,
  render: h => h(App),
  mounted() {
    store.dispatch('initConfiguration').then(() => {
      store.dispatch('loadData')
    })
  }
})

The issue I am encountering is that the state is not being updated before the subsequent action loadData is triggered, resulting in errors due to missing or uninitialized data. I want to avoid calling the loadData action directly from the initConfiguration action to adhere to best practices.

Here is my Vuex store implementation...

export default Vuex.Store({
  state: {
    metadata: {
      initialized: false,
      config: { }
    }
  },
  mutations: { 
    setConfiguration(state, config) {
      state.metadata.config = config
      state.metadata.initialized = true
    }
  },
  actions: {
    initConfiguration({commit}) {
      axios.get('configuration').then((response) => {
        commit('setConfiguration', response.data)
      })
    },
    loadData({commit, state}) {
      axios.get(state.metadata.config.tenantDataUrl) // crashes here due to undefined data
        .then((response) => { ... });
    }
  }
})

How can I properly chain actions together and ensure that the state is updated in a timely manner?

Answer №1

To make your existing code work, ensure you return your axios promise by adding a return to each axios call.

Alternatively, you can refactor the code like this:

new Vue({
  el: '#app',
  store,
  render: h => h(App),
  async mounted() {
    await store.dispatch('initConfiguration')
    await store.dispatch('loadData')    
  }
})

.

export default Vuex.Store({
  state: {
    metadata: {
      initialized: false,
      config: { }
    }
  },
  mutations: { 
    setConfiguration(state, config) {
      state.metadata.config = config
      state.metadata.initialized = true
    }
  },
  actions: {
    async initConfiguration({commit}) {
      const response = await axios.get('configuration')
      commit('setConfiguration', response.data)
    },
    async loadData({commit, state}) {
      const response = await axios.get(state.metadata.config.tenantDataUrl) // crashes here due to undefined data
     // handle response or use try/catch
    }
  }
})

If you want the vue template to update after each step, include this:

new Vue({
  el: '#app',
  store,
  render: h => h(App),
  async mounted() {
    await store.dispatch('initConfiguration')
    await this.$nextTick() // trigger vue to run getters and update computeds
    await store.dispatch('loadData')    
  }
})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React Native: Struggling with Button Styling

I am relatively new to React Native, although I have experience with React in my professional work. I'm finding that applying styles to components in React Native is a bit different than what I'm used to. Specifically, I am struggling to apply s ...

Switch Up Your Page Title Instantly Using an Anchor Tag Click

I am looking to use Javascript to change the title of a page when a specific anchor tag is clicked. <a href="index.html" title="Home">Home</a> <a href="about.html" title="About Us">About Us</a> Is it possible to achieve this by ad ...

What are the steps to take when troubleshooting an issue with saving a mongoose object?

I have implemented a node.js API that is responsible for updating a subdocument. Below, you can find the POST call for the subdocument: .put(function(req, res) { member.findById(req.params.member_id, function(err, member) { if (err) res.send(e ...

Enhance the versatility of the image upload script

My script successfully previews an uploaded image for a single upload. Now, I want to apply this script to multiple image uploads and make the readURL function dynamic so that I don't have to repeat lines of code. $(".patient_pic").on("change",funct ...

JQuery - Triggering $(document).ready() before the elements are fully loaded

While working on retrieving data from a MVC3 action that returns Json with parameters and content as a string, I encountered an issue. After appending the content to a div, a JQuery event placed in a partial view's document.ready function executes bef ...

What is the best method for ensuring image orientation is displayed correctly?

When utilizing multer node and express for uploading images to my application, I've noticed that some of the images appear rotated 90 degrees once they reach the client side. What could be causing this issue, and how can I resolve it? Just to clarif ...

How to ensure a table in MaterialUI always maintains full width without requiring horizontal scrolling in CSS?

After attempting to allocate each widthPercent value on the TableHeader so they sum up to 100%, I am still experiencing the presence of a scroll bar. I have tried setting fixed widths for each column, but this results in excess space on the right side dep ...

Sometimes, when utilizing axios to fetch an API, it may return an undefined value in specific scenarios

<template> <div class="max-w-sm rounded overflow-hidden shadow-lg bg-white"> <div class="px-6 py-4"> <div class="font-bold text-xl mb-2">{{coin.data.name}} Price Statisti ...

Tips for producing/reserving cropped images from a photo? (includes converting images to base64 format)

https://i.sstatic.net/6Nath.png Imagine having two square datasets taggedImages: { 0: {id:0, left:100, top:100, thumbSize:100, type: 'A', seasons: ['All', 'All']}, 1: {id:1, left:200, top:200, thumbSize:100, type: &apos ...

Discovering the perfect job through the utilization of agendajs

As a newcomer to NoSQL databases, I am exploring the use of the agendajs module for storing reminders in a Mongo database. Since all reminders share the same job name ('send reminder') and I am not saving the generated _id in my relational databa ...

Identifying HTTP Live Streaming on mobile devices

I am seeking a reliable method to determine if a mobile device can play HTTP Live Streaming (m3u8). Currently, I am using the following script for testing purposes: function isHLSEnabled() { var videoElement = document.createElement('video' ...

The animation unexpectedly resets to 0 just before it begins

Currently, I am developing a coverflow image slider with jQuery animate. However, there are two issues that I am facing. Firstly, when the animation runs for the first time, it starts at `0` instead of `-500`. Secondly, after reaching the end and looping b ...

Click-triggered CSS animations

Trying to achieve an effect with regular JS (not jQuery) by making images shake after they are clicked, but running into issues. HTML: <img id='s1_imgB' class="fragment"... onClick="wrongAnswer()"... JS: function wrongAnswer(){ docume ...

Top strategy for creating a customizable table using Django

Check out my new Template which includes an HTML-table and an iframe that's rendering user-uploaded pdf's: https://i.sstatic.net/Jpg0lTm2.png The main purpose is to enable users to link table entries with one or more pdf files. This part has bee ...

Incorporating font-awesome icons into your project using webpack

I have a Bootstrap template and I am trying to integrate it with FountainJS. I have included all the SCSS files from the template and everything is working fine. Now, I am trying to include Font Awesome, so I used npm install font-awesome --save and added ...

JavaScript function is returning 'undefined' instead of an integer

My JavaScript/jQuery function is not functioning correctly and instead of returning an integer, it returns undefined. function __getLastSelectedCategory(table_id) { if ( jQuery('.categories_table[data-table-id="1"]').find('td.active&apo ...

Unable to save Ajax data in session array

Currently, I am developing a cart system using jquery, ajax, and php. The issue I am facing is that the text within the HTML elements is not being added to the session array. Below is the ajax code I am using: $(document).ready(function(){ $("#car ...

Is it possible to switch the linter in grunt.js to jslint instead?

Is it feasible to switch the linter used by grunt.js from jshint to jslint, considering that I am more accustomed to using jslint over jshint as the default linter? ...

Tips for creating Selenium code to verify the asterisk symbol

Looking to create Selenium code for validating the presence of asterisks with mandatory fields such as First Name*, Last Name*, Enter Address*, and Enter Phone Number*. The validation needs to confirm the asterisk appears after each field name. Currently ...

Customize the focus function for an individual element

I am working on a custom component that needs to seamlessly integrate with the native blur and focus functions. My goal is to override these functions in order to achieve the specific functionality I need. Currently, I have managed to override the prototy ...