はじめに
Nuxt3で、以下をやろうとしていました。
- 親コンポーネントで
id
の配列を持っている - それを
v-for
して子コンポーネントにid
を渡しつつ子コンポーネントを複数表示する - 子コンポーネントの中で
id
を引数に取るAPIをコールし、返り値を表示する
このときid
ごとにAPIの返り値は異なるはずなのですが、表示される結果がすべて同じになってしまいました。
一応解決まで行けたので共有します。
環境
package.json
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": 省略,
"dependencies": {
"nuxt": "^3.10.3",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
}
}
再現するソースコード
./pages/index.vue(親コンポーネント)
<template>
<div>
<ChildComponent v-for="id in [1, 2, 3, 4]" :key="id" :id="id" />
</div>
</template>
./components/ChildComponent.vue(子コンポーネント)
<template>
<span>{{ userName }}</span>
</template>
<script setup lang="ts">
const { id } = defineProps<{ id: number }>();
const userName = ref<string | null>(null);
useFetch<string>('/api/fetchName', {
method: 'POST',
body: { id }
}).then((res) => {
userName.value = res.data.value || null;
});
</script>
./server/api/fetchName.ts
export default defineEventHandler(async (event): Promise<string> => {
const { id } = await readBody(event);
if (id === 1) return 'a';
if (id === 2) return 'b';
if (id === 3) return 'c';
return 'd';
});
上記コードで表示される期待値は以下だが、
abcd
実際は以下になる
dddd
解決方法
理由は分からないですが、以下2点を修正することで解消しました。
- APIコールを
onMounted
内で行う - それに伴い、
useFetch
ではなく$fetch
を使う
修正後のソースコード
./components/ChildComponent.vue(子コンポーネント)
<template>
<span>{{ userName }}</span>
</template>
<script setup lang="ts">
const { id } = defineProps<{ id: number }>();
const userName = ref<string | null>(null);
+ onMounted(() => {
- useFetch<string>('/api/fetchName', {
+ $fetch<string>('/api/fetchName', {
method: 'POST',
body: {id}
}).then((res) => {
- userName.value = res.data.value || null;
+ userName.value = res || null;
});
+ });
</script>
おわりに
解決はしましたが、原因が全く分かっていないので分かるいらっしゃれば教えて頂きたいです。
ライフサイクルの問題か、useFetchの内部処理(キャッシュ等)の問題かと思っていますが...