Utilize Vue 3 for setting up reactive fetching with asynchronous JSON handling

I recently upgraded to Vue 3 and I'm trying to populate a reactive object by fetching data from a JSON API.

Here's how my component looks. Surprisingly, I am not encountering any errors but the expected results are not showing up either.

<template>
  <div>
    {{ state.test.total }}
  </div>
</template>

<script>
import { reactive } from "vue";

export default {
  setup() {
    const state = reactive({
      test: null,
    });

    state.test = async () => {
      return await fetch("https://api.npms.io/v2/search?q=vue");
    };

    return {
      state,
    };
  },
};
</script>

The expectation was to display a number on the screen as per the total field in the JSON data.

Concerning state.test

When I tried outputting just state.test, this is what I got:

function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }

Do you have any suggestions on how to overcome this hurdle?

Answer №1

When you write:

a = async function test() {
}

You're setting a function to your state. However, if you write

a = (async function test() {
})();

You are still assigning a promise to a, not a value. To assign a value, you need to resolve the promise like this:

funcResult = await a;

The setup function is not appropriate for code that needs to run during the component's lifecycle. The setup function acts as a factory for your component and should always be synchronous (no async keyword) so Vue knows what to display while setup resolves. You can utilize hooks in the composition API instead:

import { onMounted, reactive } from "vue";

export default {
  setup() {
    const state = reactive({
      test: null,
    });

    onMounted(async () => {
      const response = await fetch("https://api.npms.io/v2/search?q=vue");
      state.test = await response.json();
    });

    return {
      state,
    };
  },
};

EDIT

Based on @boussadjra-brahim's answer, you can define an async setup function only if you wrap your component with <Suspense>. So you have these two options to choose from.

Answer №2

I believe that it's more advantageous to avoid delaying things.

Instance:

<template>
    <div>
        {{ result }}
    </div>
</template>


<script>
import { ref } from 'vue';

export default {
    setup() {
        const result = ref({});

        fetch('https://api.npms.io/v2/search?q=vue')
            .then(response => response.json())
            .then(data => result.value = data);

        return { result };
    },
};
</script>

Answer №3

To enhance the functionality, make sure to include the async keyword in the setup option and use await within the fetch function. Additionally, wrap the child component with a Suspense component inside the parent component:

<template>
    <div>
      {{ state.test.total }}
    </div>
</template>

<script>
import { reactive } from "vue";
export default {
  async setup() {
    const state = reactive({
      test: null,
    });

    try{
      state.test =  await fetch("https://api.npms.io/v2/search?q=vue");
     } catch (err) {
       console.error(err)
   }

    return {
      state,
    };
  },
};

Within the parent component:

<template>
  <Suspense>
    <Child/>
  </Suspense>
</template>

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

Enhancing the Calculator Functionality in a React Program

I'm struggling to incorporate a reset button into the input field, similar to CE on a calculator. I'm facing challenges when it comes to integrating it within the existing code structure. import { useRef } from "react"; import './A ...

Utilizing the power of JavaScript in an HTML file to develop a straightforward price calculator

I am new to the world of HTML coding and currently working on an assignment for my online computer course. I reached out to my professor for help, but unfortunately, he hasn't been very responsive. The task at hand is to create a basic cost calculator ...

jQuery failing to append code after being removed

I need some assistance with an issue I've run into while using jQuery's .remove(). Here is a snippet of code that showcases the problem: $( '.video-button span.glyphicon-play' ).click(function() { $( '#video-player' ).ap ...

Javascript use of overlaying dynamically generated Canvases

Currently, I am developing a game to enhance my skills in HTML5 and Javascript. In the beginning, I had static canvases in the HTML body but found it difficult to manage passing them around to different objects. It is much easier for me now to allow each ...

The rotation of Google Maps always returns to its default position when I open the map information window by clicking on it

I have successfully implemented a Google Map with tilt and heading functionality, allowing the map to rotate horizontally. However, I am facing an issue where clicking on a marker resets the map back to its original position. You can view the map by follo ...

Vue.js Issue: Image not properly redirected to backend server

Having an issue with my Vue app connecting to the backend using express. When I attempt to include an image in the request, it doesn't reach the backend properly. Strangely though, if I bypass express and connect directly from the Vue app, everything ...

Is it possible to combine Ajax, JS, HTML, PHP, and MySQL in a single project?

I am looking to create a web application and wondering if I can integrate Ajax, JavaScript, HTML, PHP, and MySQL all together? ...

Error in Babel-Loader when executing npm run build

Not being a webpack expert, I decided to upgrade from V3 to V4. After fixing the depreciation errors in my webpack config, I hit a roadblock with a syntax error from babel-loader: Module build failed (from ./node_modules/babel-loader/lib/index.js): ...

Struggling to set up the connection between React-Redux connect and the Provider store

Currently utilizing Redux with React Native for state management. I've set up the store and Provider successfully it seems, as I can utilize store.getState() and store.dispatch(action()) from any component without issue. However, I'm encountering ...

What is the alternative to $templateCache in Angular2 and how can CachedResourceLoader be utilized in its place?

While I have come across 2 similar questions on Stack Overflow and here, none of them seem to provide a solution. After delving into the Angular repository, I stumbled upon this issue where they inquire about an alternative for templateCache in Angular 2, ...

JavaScript is throwing an error stating that the requestData is undefined, even though the

Hello, I am attempting to retrieve weather information based on the country and city using the openweather api. JSON is a new concept for me in coding, so please bear with me through this learning process. Below is the code snippet that I have been workin ...

Cancel promise chain after action dispatch (rxjs)

My goal is to achieve the following: this.jobManager .queue( // initiate a job ) .then( // perform additional actions, but stop if `ABORT` action is dispatched before completion ) .finally( // carry out necessary ...

The output from the NodeJS storage module function

Attempting to implement Two-Factor Authentication in my initial NodeJS project, which serves as a learning tool for Node. While the function correctly retrieves values from data_url, when I assign it to a variable and return data_url, it returns 'und ...

JavaScript taking over the HTML footer content

I'm attempting to update the content of my footer without modifying the HTML by including a class or an id. HTML: <footer> <div> Lorem ipsum dolor sit amet, consectetur adipisicing elit. </div> </footer> Java ...

The CORS problem arises only in production when using NextJS/ReactJS with Vercel, where the request is being blocked due to the absence of the 'Access-Control-Allow-Origin' header

I've encountered a CORS error while trying to call an API endpoint from a function. Strangely, the error only occurs in production on Vercel; everything works fine on localhost. The CORS error message: Access to fetch at 'https://myurl.com/api/p ...

Using Laravel's compact function within Vue components

I am wondering how to pass variables to a Vue component in Laravel? When using blade, we can pass variables like: $now = Carbon::now(); return view('xxxxxxxx', compact('now'); This allows us to use $now in the xxxxxxxx blade file. Bu ...

Difficulty encountered in closing dialog box upon clicking NavLink in React

Currently, I am developing a React application and have integrated a dialog box using the Material-UI library's Dialog component. Inside this dialog box, there is a navigation menu that I would like to close when a user clicks on one of the navigation ...

TypeScript does not perform type checking on arrays created using the Array() constructor and filled with the fill method

Using TypeScript version 2.4.2, compiled with the --target ES6 option has interesting results. For example, when using this line of code: var coins: { coin: number}[] = [1,1,1] TypeScript throws an error: Error TS2322: Type 'number[]' is no ...

Changing pricing on pricing table with a click

Looking to implement a price changing button that functions similar to the one found at this LINK: If anyone knows of any JavaScript or other solution, please provide me with some guidance. Thank you in advance. ...

Extract a specific pattern from a string using Javascript

Currently, I am attempting to extract a specific string from a tag in javascript using the following code: document.querySelector('.title h2').textContent However, when I execute this code, I am getting a result that includes unnecessary double ...