はじめに
コジマです。
Webアプリの開発している中で
画面描画に必要なデータを取得するAPIを飛ばす処理をasyncDataに組み込もうとして
動かなくてハマってしまいました。
その原因と対処を書き記します。
原因
コンポーネントは asyncData メソッドを持たないため、サーバーサイドでコンポーネント内で非同期にデータを取得することは直接的にはできません。
まさしくこれだったんですね。
コンポーネントのvueファイルにasyncDataを書いていて、非同期にデータを取ることができなかったのです。
<template> <!-- 描画したい --> <child /> </template> <script> export default { // 省略 } </script>
<template> <div>{{responseData}}</div> </template> <script> export default { async asyncData(context){ // コンポーネントで非同期のasyncDataは動かない const responseData = await context.$axios.$get('/test/') return {responseData: responseData} } } </script>
対処
1.mounted() フック内に API コールを作成し、ロード時に data プロパティをセットすること。マイナスな側面: サーバーサイドレンダリングでは機能しません。
2.ページコンポーネントの asyncData() または fetch() メソッド内に API コールを作成し、データを props としてサブコンポーネントへ渡すこと。この方法ではサーバーサイドレンダリングでもうまく機能します。マイナスな側面: ページ内 asyncData() または fetch() が他のコンポーネントのデータをロードするため、可読性が落ちるかもしれません。
私は2の方法をとることにしました。
親(ページコンポーネント)のasyncData()で取得したデータをpropsで渡してやればよかったんですね。
<template> <!-- 描画したい --> <!-- propsで渡してあげる --> <child :responseData="responseData"/> </template> <script> export default { async asyncData(context){ // ページコンポーネントなら動く const responseData = await context.$axios.$get('/test/') return {responseData: responseData} } } </script>
<template> <div>{{responseData}}</div> </template> <script> export default { props:{ // propsを受け取ってやればOk responseData: { type: String, required: true, } } } </script>
さいごに
1年くらいNuxtやってたのにこういう原則的なことって抜けちゃってることを今更知るという。。。
ただ、今のアプリのソース、幽霊asyncData結構ありそうだなぁ、、
リファクタしたいなぁ。
この記事を面白いまたは役に立ったと思ってくれた方は是非私のTwitter(@kojimanotech)を
フォローしてくれたらうれしいです!
システムエンジニアのつらい部分のあるあるなんかをエンタメにしたチャンネルを作りました。
チャンネルはこちら
つらい部分も楽しくなればと思っているのでよかったらチャンネル登録や高評価してくれたらうれしいです。
以上、コジマでした。