Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue 3 setup reactive fetch with async json

I've installed Vue 3 and want to populate a reactive object with fetch from a JSON API.

My component looks like below. I don't get any errors but I don't get any results 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>

I expected to get a number on the screen because that's what's in total in the JSON file.

On state.test

If I only output state.test I get the output below.

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); }); }

Any idea how I can get around it?

like image 329
Jens Törnell Avatar asked Oct 24 '20 14:10

Jens Törnell


People also ask

Is it possible to use async setup function in Vue?

Thus setup function should always be synchronous (no async keywrord), otherwise vue would not know what it should display while setup is resolving. Luckily you can use hooks in composition API: Taking into account @boussadjra-brahim answer, you can actually define async setup function, but only in case if you wrap your component with <Suspense>.

What is the difference between Vue 2 and Vue 3 reactivity?

The reactive proxy doesn’t equal to the original object in terms of identity comparison ( === ). It requires more code compared to the Vue 2 “automatic” reactivity. The bottom line is that Vue 3 reactivity is a flexible and powerful system, which can be used both by Vue and non-Vue developers.

How to add a property to a reactive object in Vue?

adding/removing a property to/from an object (such as obj.newKey = value) modifying the length of an array (such as arr.length = newLength) Fortunately, to deal with these limitations Vue provides us with the Vue.set API method, which adds a property to a reactive object, ensuring the new property is also reactive and thus triggers view updates.

What's new in VUE 3?

The reactivity system in Vue 3 was completely rewritten in order to take advantage of the ES6 Proxy and Reflect APIs. The new version exposes a feature-rich reactivity API which makes the system far more flexible and powerful than before. The Proxy API allows developers to intercept and modify low-level object operations on a target object.


Video Answer


2 Answers

When you do:

a = async function test() {
}

You're assigning a function to your state. But if you you do

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

You're still assigning a promise to a, rather than a value. If you want to assign a value you need to resolve this promise:

funcResult = await a;

Your setup function is not a proper place for code that should be executed during lifetime of your component. You can think of setup function as a factory for your component. Thus setup function should always be synchronous (no async keywrord), otherwise vue would not know what it should display while setup is resolving. Luckily you can use hooks in composition API:

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

Taking into account @boussadjra-brahim answer, you can actually define async setup function, but only in case if you wrap your component with <Suspense>. So you can either go with this or that variant.

like image 91
deathangel908 Avatar answered Nov 08 '22 22:11

deathangel908


I think it's better not to wait.

Example:

<template>
    <div>
        {{ state }}
    </div>
</template>


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

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

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

        return { state };
    },
};
</script>
like image 39
Matt Deacalion Avatar answered Nov 09 '22 00:11

Matt Deacalion