「APIから持ってきたデータを表示する」そんなページをSPAで構築する際には、Vue.jsの場合、「created()」フックなどにAPIを叩く処理を書くパターンが多いのではないかと思います。
Nuxt.jsで開発する場合にも、「created()」フックを使って同様のことが行えます。
しかし「created()」は、あくまでブラウザ側での実行になります。Nuxt.jsを使ってSSRを行いたい場合には、サーバー側でデータ取得の完了まで行いたいケースが多いはずです。
この記事では、そんな時に使える「asyncData()」と「fetch()」について紹介します。
asyncData()について
asyncDataの使い方
コンポーネント(.vueファイル)内で、以下のように呼び出すことが可能です。 (※「asyncData()」を使うことができるのは、「pages」ディレクトリ配下のコンポーネントだけです)import axios from 'axios'
export default {
asyncData() { // promiseを返すようにする
return axios.get('https://URL')
.then(result => {
return {
itemData: {
...result.data
}
}
})
}
}
// もちろん、以下のように「async/await」で書けます。
// async asyncData() {
// const result = await axios.get('https://URL')
// return {
// itemData: {
// ...result.data
// }
// }
// }
まず、promiseを返すように書く必要があります。 (promiseの解決をサーバー側で待ってから、クライアント側に処理が渡ります)
そして、data()オプションと同じように、オブジェクトを返すようにします。 返したオブジェクトは、data変数にマージされます。
※asyncData()とdata()で、同じキー名の変数を入れないように注意です。 (data()で上書きされてしまうため)
「context」について
「asyncData()」は、サーバー側での実行(コンポーネントのインスタンス化前)になるので、処理内で「this」を使うことができません。 代わりに、引数として「contextオブジェクト」が渡されます。
contextオブジェクトには、リクエスト情報やパラメータなどのデータが入っています。 必要なデータには、contextオブジェクトを介してアクセスする形になります。
import axios from 'axios'
async asyncData(context) {
// URLのパラメータを取得したり。
const id = context.params.id
const result = await axios.get('https://URL' + id)
return {
itemData: {
...result.data
}
}
}
asyncData()の実行タイミングについて
asyncData()がサーバー側で実行されるのは、アプリケーションへの初回アクセス時のみです。 (URLへの直接アクセス・リロードなどの形でページに遷移した場合など)
最初の一回はサーバー側で実行されますが、それ以降はSPAとして動作することになります。(ブラウザ側で実行される)
asyncData()は、
・サーバー側 ・クライアント側
上記のどちらでも実行されるので、その点をコード書く時には意識しておく必要があります。
例えば「localStorage」は、クライアント側でしかアクセスできません。(サーバー側ではエラーになります。) なので「process.client」などを利用して条件分岐するなど、工夫が必要です。
if (process.client) {
// ブラウザ側でのみ行いたい処理
}
fetch()について
fetch()はサーバー側でデータを取得して、その値をstoreに格納したい場合に使うメソッドです。
使い方自体は、ほとんど「asyncData()」と一緒です。
import axios from 'axios'
export default {
async fetch(context) {
const result = await axios.get('https://URL')
context.store.commit('testMutations', result.data)
}
}
asyncData()と同様に、promiseを返すようにします。そして、上記の例のようにデータをstoreに格納すればOKです。(contextオブジェクトを介して、storeにアクセスすることが可能です。)
asyncData()と同様に、最初の一回はサーバ側で実行されて、 その後は、fetch()を利用しているコンポーネントにアクセスする度に、毎回ブラウザ側で実行されます。
asyncData()もfetch()も、似た挙動をするメソッドですが、
- asyncData():取得してきたデータをdata変数として扱いたい時
- fetch():取得してきたデータをstoreに格納したい時
上記のように、目的に応じて使います。