Nuxt 3 cung cấp 3 data-fetching primitives: useFetch (tiện lợi, auto-keyed), useAsyncData (linh hoạt, multi-source), và $fetch (raw, cho user-triggered actions).
useFetch: wrapper tiện lợi nhất — tự động deduplicate, cache key từ URL:
// Chạy cả server lẫn client, SSR-compatible
const { data, pending, error, refresh } = await useFetch('/api/users', {
lazy: false, // true = không chặn navigation
server: true, // false = chỉ fetch client-side
transform: (data) => data.users,
})useAsyncData: flexible hơn cho custom async logic:
const { data } = await useAsyncData('unique-key', async () => {
const [users, posts] = await Promise.all([
$fetch('/api/users'),
$fetch('/api/posts'),
])
return { users, posts }
})$fetch: raw fetch (ofetch under the hood) — không tự cache hay deduplicate:
// Dùng trong event handlers, actions — không trong setup
async function submitForm() {
const result = await $fetch('/api/users', {
method: 'POST', body: formData.value
})
}Rule of thumb: setup/navigation data → useFetch/useAsyncData.
User-triggered actions → $fetch.
useFetch: convenience wrapper — auto-deduplicates, cache key from URL:
const { data, pending, error, refresh } = await useFetch('/api/users', {
lazy: false,
transform: (d) => d.users,
})useAsyncData: flexible for custom async logic with multiple requests:
const { data } = await useAsyncData('key', async () => {
const [users, posts] = await Promise.all([$fetch('/api/users'), $fetch('/api/posts')])
return { users, posts }
})$fetch: raw ofetch — no auto-caching:
async function submit() {
const result = await $fetch('/api/users', { method: 'POST', body: form.value })
}Rule: navigation data → useFetch/useAsyncData.
User actions → $fetch.