A Composable for Loading
Loading data from a file is the same every time: a ref for the data, one for loading, one for an error message, and onMounted with fetch(). Only the file changes. That's a job for a composable, with the file's address as its parameter:
import { onMounted, ref } from "vue";
export function useFetch(url) {
const data = ref(null);
const error = ref("");
const loading = ref(true);
onMounted(async () => {
const response = await fetch(url);
if (!response.ok) {
error.value = "Sorry, this couldn't be loaded.";
} else {
data.value = await response.json();
}
loading.value = false;
});
return { data, error, loading };
}A component that needs data calls it with the file's name and gets the three refs:
<script setup>
import { useFetch } from "./useFetch.js";
const { data, error, loading } = useFetch("menu.json");
</script>What's worth noticing:
onMountedworks in a composable too, and it belongs to the component that calls the composable: the data is loaded when that component is mounted. Two components that calluseFetch()each load their own file, each when it's mounted, and each has its owndata,errorandloading.datastarts asnull, which means “nothing yet”: the composable can't know what the file holds, an array, an object or text. The template shows the list only onceloadingisfalse, and by thendataholds the menu.- The error message is a general one, because the composable loads anything.
Composables like this one are in almost every Vue app, and libraries offer ready-made ones. VueUse, a popular collection of composables, has its own useFetch(), and a useLocalStorage() too.
Instructions
- 1
Write
useFetch(url)inuseFetch.js: move the three refs andonMountedfromApp.vueinto it, withmenurenamed todata,urlin place of"menu.json", andSorry, this couldn't be loaded.as a general message. Return{ data, error, loading }. InApp.vue, import it, take the refs out withconst { data, error, loading } = useFetch("menu.json");, and showitem in datain the list. - 2
Now the reviews: in
Reviews.vue, loadreviews.jsonwithuseFetch(), and show each review likeAnna: The best carrot cake in town., withLoading…while they load, as the menu does.