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.
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?
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>.
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.
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With