Vue/Vuex - Module two relies on module one, which in turn fetches data from the server

Take a look at this:

import accountModule from '@/store/modules/account/account';
import otherModule from '@/store/modules/other/other';

export default new Vuex.Store({
  modules: {
    account: accountModule,
    other: otherModule,
  }
});

The initialization of data in the other module is dependent on the account module due to user-specific settings. For instance, other.state.list relies on account.state.settings.listOrder. However, I need the data for the account module to be retrieved from the server, which involves an asynchronous process. Therefore, when setting up other, it cannot directly reference account.state.settings.listOrder as the server response might not have been received yet.

I attempted to export a promise in the accountModule that resolves with the module itself, but this approach did not work as expected.

import accountModulePromise from '@/store/modules/account/account';

accountModulePromise.then(function (accountMoudle) {
  import otherModule from '@/store/modules/other/other';

  ...
});

However, I encountered an error stating that import statements must be top-level.

A different method that was unsuccessful involved using await like so:

let accountModule = await import('@/store/modules/account/account');
import otherModule from '@/store/modules/other/other';
...

This resulted in an error indicating that await is a reserved word. This is confusing because according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import, this should be a valid operation.

Answer №1

Your previous code block failed to work because the await keyword must be contained within an async function.

Remember, you can only use the await keyword inside async functions. If you attempt to use it outside of an async function, a SyntaxError will occur.

Referenced from MDN.

You might want to explore Dynamic Module Registration:

accountModulePromise.then(async () => {
  let otherModule = await import('@/store/modules/other/other');
  store.registerModule('other', otherModule.default);
});

However, when attempting to access state or dispatch actions, you'll need to ensure that the module is registered, which can become cumbersome.

In my opinion, it could be beneficial to restructure your module organization for better decoupling. Consider moving your initialization logic to main.js or App.vue, and then dispatch actions from there to update module states.


Updates

Building on your recent updates regarding decoupling your store, one approach could involve storing your list without any specific order, sorting it dynamically when needed. This can be achieved using:

Computed property:

...
computed: {
  list () {
    let list = this.$store.state.other.list
    let order = this.$store.state.account.settings.listOrder
    if (!list || !order) return []
    return someSort(list, order)
  }
},

beforeCreate () {
  this.$store.dispatch('other/fetchList')
  this.$store.dispatch('account/fetchListOrder')
}
...

Or Vuex getters:

...
getters: {
  list: (state) => (order) => {
    return someSort(state.list, order)
  }
}
...
...
computed: {
  list () {
    let order = this.$store.state.account.settings.listOrder
    return this.$store.getters['others/list'](order)
  }
}
...

Answer №2

Let's say you have two modules - one with state retrieved from the server and another whose state relies on the first module, right?

Here's a potential solution:

Start by initializing your modules with empty 'state'. Then, in the accountModule, create an action to set up the state fetched from the server. Use a getter on other to sort the list accordingly. Lastly, trigger your action during app initialization.

const account = {
    namespaced: true,
    state: {
        listOrder: ''
    },
    mutations: {
        setListOrder (state, newListOrder) {
            state.listOrder = newListOrder
        }
    },
    actions: {
        async fetchServerState (ctx) {
            let result = await fetch("/path/to/server")
            ctx.commit('setListOrder', result.listOrder) 
            // This is just an example; adjust based on your response
        }
    }
}

const other = {
    namespaced: true,
    state: {
        unorderedList: []
    },
    getters: {
        list (state, getters, rootState) {
            return someSort(state.unorderedList, rootState.account.listOrder);
        }
    }
}


In App.vue (or similar):

created () {
    this.$store.dispatch('account/fetchServerState')
}

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

Having difficulty using replaceWith to replace text in jQuery

My favorite script successfully adds data to SQL and replaces HTML tags. I have included a text like Add Favorite and used replaceWith to display Remove Favorite. However, the output is not as expected, as shown in the image below. https://i.sstatic.net/x ...

Creating a Webgrid in MVC and integrating it with a custom class in AngularJS

Hey there, I'm a beginner when it comes to AngularJS and I'm looking to bind the webgrid within the method of AngularJS. $scope.SaveDetails = function () { debugger; var UserID = '@Session["ID"]'; ...

What is the best way to create a mapping function in JavaScript/TypeScript that accepts multiple dynamic variables as parameters?

Explaining my current situation might be a bit challenging. Essentially, I'm utilizing AWS Dynamodb to execute queries and aiming to present them in a chart using NGX-Charts in Angular4. The data that needs to appear in the chart should follow this fo ...

Checking the validity of a username through regex

I have implemented a Username field validation in Vue using regex. A key down event triggers the method below with each keystroke: userNameValidation(event) { if (!event.key.match(/^[a-zA-Z0-9._]+$/)) { event.preventDefault(); } ...

Leveraging Material-UI: Utilize props in useStyles method while employing Array.map()

After delving into the world of passing props to makeStyles in Material-UI, I stumbled upon this insightful answer. The solution presented involves passing props as a variable, which is quite useful. However, my aspiration is to extend this functionality t ...

Is there a way to detect esbuild's build errors and execute a script in response?

Does anyone know how to handle esbuild's build error and trigger a script afterward? I'm integrating it into my workflow with npm, VSCode, and pure JavaScript. I've searched everywhere but haven't found any information on this specific ...

Gathering information from the server once it has completed its processing phase

Looking to retrieve data from my server after processing it. Specifically, I want to transfer the processed information to the front end. Situation: A document gets uploaded to Google Cloud, data is extracted and stored in Firestore, then that extracted d ...

Using the Nodejs Array prototype filter method within a JSON object

Attempting to create a function that filters and returns specific strings within JSON data. Any advice is appreciated. Thank you! [ { line: '{"status":"waiting"}' } ] var body_W = []; body_W.push({line: JSON.stringif ...

Is it possible to add a class to the parent element when the input value of a sub-child element is

Is there a way to select and add a class to an li element in which the sub-child input is empty when clicking on button #btn-modal-clear? If so, what is the best approach to achieve this? Example HTML Code: <li>...<li> <li> <a c ...

Using React Hooks and useRef to Retrieve the clientHeight of Dynamically Rendered Images

I'm currently in the process of creating a dynamic image grid and need to determine the exact height of each image in pixels so I can adjust the layout accordingly. However, I've encountered an issue with accessing ref.current.clientHeight as it ...

Tips for retrieving the value of dynamically added input fields

I am facing some challenges with JavaScript. I want to dynamically add a form to my HTML document when the user clicks on a button. Here is the code I have written: plusBtn.addEventListener('click', () => { const newLine = document.createE ...

What is the best method for debugging dynamically created routes in Express using debug statements?

Currently diving into an ongoing Node/Express/Mongoose project, I am unraveling the intricacies of the code to grasp its functionality. The dynamic generation of Express routes adds another layer of complexity, with functions setting up routes by passing i ...

Can you suggest a simple method for implementing the "componentDidUpdate()" lifecycle method using just JavaScript?

I've been curious about replicating the componentDidUpdate() lifecycle method in JavaScript on my own. It got me thinking, how did React and Vue.JS create their own lifecycle methods? I attempted to study the minified version of Vue.JS but found it qu ...

eliminate particular item, from duplicated component

I have a Javascript code that allows me to add (clone) and delete an element. $('#btnAdd1').click(function (event) { var num = $('.linguas').length; var newNum = new Number(num + 1); var newElem = $('#input_' + nu ...

An unexpected error occurred in the Angular unit and integration tests, throwing off the script

I seem to be facing a recurring issue while running unit/integration tests for my Angular project using Karma. The tests have a 50:50 success/failure rate, working fine on my machine but failing consistently on our build server, making the process quite un ...

Directories odejs ode_packages pminary ode_packages pminary pm-cli.js’

Encountering this frustrating Node.js issue on my Windows system has been a common occurrence for me: npm --version node:internal/modules/cjs/loader:1093 throw err; ^ Error: Cannot find module 'C:\Program Files\nodejs\node_modules& ...

Leveraging the Power of JavaScript within Angular 12

Currently, I am in the process of learning how to utilize Angular 12 and am attempting to create a sidenav. While I am aware that I can use angular material for this task, I would prefer not to incorporate the associated CSS. My goal is to integrate this ...

Tips for transforming information into JSON format

Imagine having a file with data in CSV or TXT format, such as: Name, Surname, Age, Occupation Gino, DiNanni, 19, Student Anna, Kournikova, 27, Programmer (Extra spaces have been added to enhance readability) The goal ...

Returning from a find operation in Node.js using Mongoose and MongoDB collections involves implementing a specific process

When attempting to find an element in a MongoDB collection using Mongoose in Test.js, the console.log is not being executed. Within Test.js, the console.log is failing to display the data retrieved from the MongoDB collection. var model = require(' ...

Bootstrap tab toggle feature

I'm currently facing an issue with Bootstrap's tab component. I need help figuring out how to hide a lorem ipsum section and show a hidden div when a specific tab is clicked, and then revert the changes when a different tab is selected. $(func ...