Let's break it down simply
Every network request needs more than just a success path — it needs loading, error, and empty states too. Check response.ok and use try/catch/finally. If the component unmounts, you can use an AbortController to cancel a request you no longer need.
vue
<script setup>
import { ref, onMounted } from 'vue'
const users = ref([])
const loading = ref(true)
const error = ref('')
onMounted(async () => {
try {
const response = await fetch('/api/users')
if (!response.ok) throw new Error('Request failed')
users.value = await response.json()
} catch (cause) {
error.value = cause instanceof Error ? cause.message : 'Unknown error'
} finally {
loading.value = false
}
})
</script>You should see
loading → users list OR error messageTry it yourself
Fetch data from a public API and show all four states: loading, error, empty, and success.
Vue — Scaling Up — Vue.js