【Nuxt3】useFetchの誤った使い方
動作確認環境
- Nuxt 3.13.0
useFetch の警告
Nuxt 3 で API 呼び出しに便利な useFetch
(または useAsyncData
) ですが、バージョンアップした際に、ボタンクリック等のイベントハンドラで呼び出そうとすると警告が出るようになりました。
nuxt3 のドキュメントにも少しだけそのことに触れられており、ドキュメントで紹介されている動画で useFetch
の誤った使い方について説明されていたので備忘録としてまとめます。
誤った使い方の例
以下は動画内で使われていた例の簡易版です。
簡易なログインフォームで、ユーザー名とパスワードを入力してログインボタンを押すと useFetch
を実行します。
<script setup lang="ts">
const userName = ref("");
const password = ref("");
const body = computed(() => ({
userName: userName.value,
password: password.value,
}));
const onSubmit = async () => {
const { error } = await useFetch("/api/login", {
method: "POST",
body,
onResponse() {
callCount.value++;
},
});
};
</script>
<template>
<form class="form" @submit.prevent="onSubmit">
<input type="text" placeholder="userName" v-model="userName" />
<input type="text" placeholder="password" v-model="password" />
<button>Login</button>
</form>
</template>
useFetch
はリアクティブ値を監視するため、その値に変更がなされるたびに再リクエストを実行します。
そのため、ログインボタンをクリックした時だけ実行してほしいところ、こちらの例では一度onSubmit
を実行した後に userName と password の値が変更される度に再リクエストが実行されてしまいます。
※stackblitz に例と同じような環境を用意したので、実際に動かしたい人は使ってみてください。
解決策 1
warning にもあるように、$fetch
はリアクティブデータの監視はないため、警告に従い $fetch
を使用すればイベント時にのみリクエストを実行できます。
const onSubmit = async () => {
const { error } = await $fetch("/api/login", {
method: "POST",
body,
onResponse() {
callCount.value++;
},
});
if (!error.value) {
didItWork.value = true;
}
};
解決策 2
useAsyncData でラッパーしている等の理由で $fetch に変えたくない場合は、setup()
のトップレベルで宣言し、refresh()
や execute()
をイベントハンドラで呼び出せば再リクエストが勝手に送られません。
<script setup lang="ts">
const { execute } = await useFetch('/api/login', {
method: 'POST',
body,
onResponse() {
callCount.value++;
},
immediate: false, //即時実行を無効にする
watch: false // リアクティブデータの監視・再リクエストを無効にする
});
const onSubmit = async () => {
await execute();
...
};
</script>
正直watch:false
を設定すれば監視をストップできるので、トップレベルで宣言せずともリアクティブイベント内で呼び出しても動作上問題なさそうですが、 useFetch
の強みはリアクティブデータを監視してくれることなので、「それを無効にするなら$fetch
使ってね」という方針なのかなと推測しています。
Discussion