Consecutive interdependent operations within a Vuex action

I'm currently working on a Vue application that is pulling data from the Contentful API. I have a thumbnail (image) field for each entry and I want to extract the main colors as hexadecimal values and store them in the state for use throughout the app.

To achieve this, I am using a Vuex action called getAllProjects to query the API, utilize Vibrant library (node-vibrant), and then commit the response to the state.

async getAllProjects({ commit }) {
    let {
      fields: { order: order }
    } = await api.getEntry("entry");
    let projects = order;

    projects.forEach(p =>
      Vibrant.from(`https:${p.fields.thumbnail.fields.file.url}`)
        .getPalette()
        .then(palette => (p.fields.accent = palette.Vibrant.hex))
    );

    console.log(projects);

    // Commit to state
    commit("setAllProjects", projects);
  }

Before calling commit, I can see that the desired hex values are indeed added under the accent key when logging the contents of projects. However, upon inspecting the mutation payload in devtools, the accent key seems to be missing, causing it not to end up in the state.

I am looking for guidance on how to structure these tasks so that the commit only executes once the API call and Vibrant process have run sequentially?

Answer №1

In Vue, simply adding a property to an object will not make it reactive; instead, you should use the Vue.set method.

Consider replacing the forEach loop with the code snippet below, which utilizes Vue.set to add the new property:

    for (let i=0; i<projects.length; i++)
      Vibrant.from(`https:${projects[i].fields.thumbnail.fields.file.url}`)
        .getPalette()
        .then(palette => (Vue.set(projects[i].fields, accent, palette.Vibrant.hex)))
    );

UPDATE: Although changing the loop from forEach to a standard for loop might not be necessary here since we are assigning values to an object property of projects rather than a primitive value.

Answer №2

I don't spend a significant amount of time on StackOverflow, so if the solution above works for you, I'm glad.

However, please be aware that by following that solution, you may receive console warnings advising against directly mutating state.

The reason for these warnings is that while Vue.set() does help Vue recognize when a change has been made reactively, especially within deeply nested objects, the issue arises when the object is being constantly altered in a loop.

In this scenario, it's not the mutator call that is changing the state - instead, Vue.set() is modifying the state with each iteration.

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

Is there a way to accomplish this without using settimeout?

Whenever the Like button is pressed, I want to trigger the loading process I expect to see LOAD_POST_SUCCESS immediately after LIKE_POST_SUCCESS Pressing the Like button should initiate the load process After LIKE_POST_SUCESS, I want to see LOAD_POST_SU ...

"Efficient Querying with MYSQL XDEVAPI Through Multiple OR (II) Requests

Currently, I am utilizing the XDEVAPI and attempting to incorporate the or(||) statement in JavaScript. However, it appears to malfunction after 1 or/(||) statements have been included. I need to fetch data from the database based on 5 distinct statuses: . ...

evaluating an object against null

When comparing two objects a and b, it is necessary to ensure that one of them is not null. However, deciphering this can be quite chaotic. {} - null => -0 [] - null => 0 1 - null => 1 "1" - null => 1 true - null ...

Create a Buffer that includes all the characters of the alphabet when converted to

My current project involves using Node.js to generate secure, random tokens. Here is a snippet of the code I'm using: crypto.randomBytes(32).toString("hex"); // dd89d6ab1a7196e8797c2da0da0208a5d171465a9d8e918d3b138f08af3e1852 Although this method wo ...

The filter on the mobile version is not displaying correctly

When I select a category in the input filter, only items with the same category are displayed when clicked. However, when I click on "Others" on the desktop version, only rows with that category are shown, but on mobile after resizing and filtering, nothin ...

Manipulating the DOM with Javascript and jQuery: Adding a new element and retrieving its reference

I am encountering an issue with a Web App that relies on JavaScript and jQuery. Essentially, the website includes a button that triggers a JavaScript function when clicked. Within this function, there are two other functions named Foo and Bar. Foo generate ...

A step-by-step guide on implementing ng-annotate to your code

Is there a way to run ng-annotate through the command line? I am attempting to combine and minify Angular, Angular Routes, and my own script.js into one file. When I use grunt uglify:app1, I encounter an injection error. While my code successfully minifies ...

Uploading files with Multer and handling the JSON object

Is there a way to send both a file and a JSON object containing data using multer? I came across this thread, but it only explains how to attach one field at a time. Here's what I currently have on the client side: request .post(uploadPOSTUrl) . ...

Words program with the header feature incorporated

Hello, I am currently working with Laravel to build an HTML page and have successfully converted it to MS Word. However, I am now trying to add a header inside. Can anyone help me achieve this? Here is a snippet of my code: <body> <a class= ...

Is there a way to immobilize an object in JavaScript without resorting to Object.freeze()?

Is there a way to freeze the following object without relying on Object.freeze()? Let's find out: const obj = { a:'test', b:'Something' } ...

Steps for opening a clicked link in a new tab:

I have a link on my page that I would like to open in a new tab when clicked, but it doesn't seem to be working. Can anyone offer some suggestions or help? So far, I've tried the following code: <a target="_BLANK" ng-href="{{news.url ...

What could be causing my C# function to not be triggered by AJAX?

I am attempting to invoke this specific C# method: [WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public static string getJSONdata() { string jsonString = ""; using (SqlConnection con = new SqlConnection(conn ...

Unable to loop through using ngFor

I have a component that retrieves data from the back-end and groups it accordingly. Below is the code snippet: getRecruitmentAgencyClientPositions(): void { this._recruitmentAgencyClientsService.getRecruitmentAgencyClientPositions(this.recruitmentAge ...

What are some potential causes of webpack-dev-server's hot reload feature not working properly?

Having an issue with my React project. When I try to use hot reload by running "npm start" or "yarn start" with webpack-dev-server configured (--hot flag), I'm getting the error message: [error message here]. Can anyone assist me in troubleshooting th ...

Incorporate the newest version of SASS in your Nuxt project using the @

Currently, I am implementing Sass into my project. I have successfully installed "node-sass" and "sass-loader", allowing me to utilize imports, variables, and other features of Sass. However, I am encountering an issue with using "@use" to employ a @mixin ...

having difficulty sending the username and password from the HTML page to the controller in AngularJS

In my AngularJS controller, I am having trouble retrieving the values of the username and password fields after submitting the login form. Here is the HTML code for the form: <form class="form-signin" action="" method="post"> ...

What is the best way to incorporate an exception for the printThis() element?

Is there a way to exclude a specific div from being printed when using the printThis() function? For example: <div id="print-it"> <div>hello</div> <div id="no-print-this"> <button>must be show on page but not print</but ...

It appears that the JavaScript global dynamic variable is undefined as it changes from function to function, suggesting it might be

I'm encountering an issue with the way these two functions interact when used in onclick calls of elements. Due to external circumstances beyond my control, I need to keep track of when and how elements are hidden. Everything works perfectly as inten ...

Capturing screenshots with Selenium in Node.js is proving to be quite sluggish

My current project involves using Selenium with Mocha in Node.js for UI testing on a website. I want to capture screenshots after each test to review and share the results visually. The challenge arises when there are AJAX calls and JavaScript animations ...

How to create a responsive image that appears over a button when hovering in Bootstrap?

My goal is to display an image over a button when hovering. I've tried adding the .img-responsive class in Bootstrap while including the image in the HTML, but it's not working as expected with my current method of loading images. The buttons the ...