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?
Advertisement
Answer
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.