【Vue3】ネストされたデータが N/A になる原因と対策

はじめに

Vue でテーブルを作成する際、ネストされたオブジェクトの値を取得しようとして、 N/Aundefined になってしまう問題 に直面したことはありませんか?

たとえば、以下のようなデータを CommonTable.vue に渡したとします。

{
"id": 1,
"user": {
"name": "田中 太郎"
},
"homework": "数学の問題集",
"deadline": "2024-12-31",
"status": 1
}

しかし、 user.name を取得しようとしてもうまく表示されないことがあります。
実際に私も CommonTable.vueuser.name を渡した際に、 N/A になってしまう問題に直面しました。

その 原因解決方法 を詳しく解説します!

N/A になる原因

Vue では、オブジェクトのプロパティを item[header.key] のように直接取得しようとすると、ネストされたキーには対応できません。

<td v-for="(header, index) in headers" :key="index">
{{ item[header.key] || 'N/A' }} <!-- ❌ user.name は取得できない -->
</td>

上記のコードでは、 header.key = 'user.name' の場合、 item['user.name'] のように処理されてしまうため、undefined となる のです。
(JavaScript では item['user'] はオブジェクトですが、 item['user.name'] というキーは存在しません)

解決策:getValue 関数を作成する

ネストされたオブジェクトの値を正しく取得するために、 getValue 関数を作成しましょう!

修正後の CommonTabel.vue

<script setup>
import { Link } from '@inertiajs/vue3';

/**
* ネストされたキーの値を取得する関数
*/
const getValue = (item, key) => {
return key.split('.').reduce((obj, k) => obj?.[k], item) || 'N/A';
};

defineProps({
headers: Array,
items: Array,
linkRoute: String
});
</script>

<template>
<table class="table-auto w-full text-left whitespace-no-wrap">
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index"
class="px-4 py-3 title-font tracking-wider font-medium text-gray-900 text-sm bg-gray-100"
:class="header.class">
{{ header.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td v-for="(header, index) in headers" :key="index" class="border-b-2 border-gray-200 px-4 py-3">
<template v-if="header.key === 'id'">
<Link class="text-blue-400 hover:underline" :href="route(linkRoute, { id: item.id })">
{{ item.id }}
</Link>
</template>
<template v-else-if="header.key === 'status'">
<span v-if="item.status === 1" class="inline-block w-20 text-center text-green-700 bg-green-100 rounded-lg p-2">実施中</span>
<span v-if="item.status === 0" class="inline-block w-20 text-center text-red-700 bg-red-100 rounded-lg p-2">完了</span>
</template>
<template v-else>
{{ getValue(item, header.key) }}
</template>
</td>
</tr>
</tbody>
</table>
</template>

getValue 関数の仕組み

const getValue = (item, key) => {
return key.split('.').reduce((obj, k) => obj?.[k], item) || 'N/A';
};

この関数は、以下のように動作します。

  1. key.split('.') で、user.name['user', 'name'] のように分割
  2. reduce を使って item をたどる
  3. obj?.[k] を使って安全に値を取得(undefined を回避)
  4. 値が undefined の場合、'N/A' を返す

つまり、以下のように動作します。

const item = {
user: { name: "田中 太郎" }
};

getValue(item, "user.name"); // "田中 太郎"
getValue(item, "user.age"); // "N/A"(存在しないキー)
getValue(item, "homework"); // "数学の問題集"

まとめ

N/A になる原因

  • item[header.key] では user.name のようなネストされたキーを取得できない

解決策

  • getValue 関数を作成し、key.split('.') を使ってオブジェクトをたどる

メリット

  • ネストされたデータにも対応できる
  • undefined エラーを防げる
  • 汎用的に使える(他のコンポーネントにも応用可能)

こんな時にも応用できる!

この getValue 関数は、他の Vue コンポーネントでも活用できます!
たとえば、 フォームのバリデーションエラーの表示ネストされたデータのフィルタリング などにも応用できます。

Vue で undefined に悩まされたら、ぜひ getValue を試してみてください!

あなたの Vue 開発をもっと快適に!

この記事が役に立ったら、ぜひシェアしてくださいね! 🚀
質問や感想があれば、コメントで教えてください! 🎉

コメント

タイトルとURLをコピーしました