Nuxt2.12.0でfetch methodが新しくなりました。
...fetch?
っていうか、fetchって使います? 多分使わないと思います。なぜならasyncDataと機能的にほぼ同じなので。fetchにできることは全部asyncDataで出来ていました。
新しくなったというか、ついに定義された真のfetch
で、2.12からは完全に新しくなりました。将来的にはむしろasyncDataを不要にしていくと思います(後述)
APIドキュメント: https://nuxtjs.org/api/pages-fetch
要点としては
- pageComponent限定の機能ではなくなった
- fetch methodの引数にcontextを受け取らなくなったかわりに、thisが使えるようになった(なのでpropを用いたfetchなどが可能に)
- thisに
$fetch
,$fetchState
が生えた -
this.$fetch()
で再実行ができるようになった
というあたりです。
fetch処理中の表示の出し分け
data() {
return {
post: {}
}
},
async fetch() {
this.post = await this.$http.$get(
`${this.api}${this.$route.params.id}`
)
},
fetchでapi叩いてthis.postに入れるとします。
<template>
<p v-if="$fetchState.pending">Loading...</p>
<p v-else-if="$fetchState.error">Error: {{ $fetchState.error.message }}</p>
<div v-else>
<h1>{{post.title}}</h1>
<div>{{post.body}}</div>
</div>
</template>
従来のページコンポーネントでは非同期処理が完了してからページ遷移・表示が行われていましたが、今回新しくコンポーネント単位になったことによりクライアントサイドで実行される場合には処理中の表示が発生します。
そこで 「実行中/エラー/実行完了」 の3つの表示を作るわけですが、$fetchStateにはその状態が自動的に入るので、template側ではこのように表示を出し分けることができます。
図
イメージを図にするとこんな感じでしょうか。fetchはmount前(SSR含む)とmethodを叩いたときに呼ばれます。pageComponentではないので、propの値に応じてfetchするようなコンポーネントも作りやすいと思います。
propの値でfetchする例
古いツイートなので$isFetchingとか変数名が異なってますが、propの値を使ってfetchしてSSRする例です(画像2枚目)。
fetchOnServer: false
にすることで一部のコンポーネントはクライアント処理のみにするといったこともできます(画像3枚目)
仕組み
async function $fetch() {
this.$nuxt.nbFetching++
this.$fetchState.pending = true
this.$fetchState.error = null
this._hydrated = false
let error = null
const startTime = Date.now()
try {
await this.$options.fetch.call(this)
} catch (err) {
error = normalizeError(err)
}
const delayLeft = this._fetchDelay - (Date.now() - startTime)
if (delayLeft > 0) {
await new Promise(resolve => setTimeout(resolve, delayLeft))
}
this.$fetchState.error = error
this.$fetchState.pending = false
this.$fetchState.timestamp = Date.now()
this.$nextTick(() => this.$nuxt.nbFetching--)
}
この辺の処理は上記のコードにある通り、fetchメソッドの実行が完了するまでは $fetchState.pending
がtrueになり、fetchメソッドでエラー発生した場合には $fetchState.error
にエラーオブジェクトが入るという形になっています。
つまり、fetchメソッドの中では敢えてtry catchせずエラーをそのまま投げるように書くことになります。
asyncDataとの違い
これでやっとasyncDataと住み分けができてきた感じです。
現状でfetchに無いのは context です。以前のfetchには引数に渡されていましたが今回の変更で無くなりました。
redirectやresponseのstatusCodeを設定するにはcontextが必要ですが、fetchでは使えないのでしょうか。現状では使えません。そういう処理のためには引き続きasyncDataが必要です。
Nuxt 3: Introducing fetch() hook
Context
fetch hook does not receive any context as 1st argument anymore since it has access to this.
The context will be updated to be available through this.\$ctx, this.\$config and this.\$nuxt, learn more on #25
ですがRFCにあるように将来的には this.$ctx が生えるようになるようです。
こちらを使うことでasyncDataの役割はfetchでできるようになっていくと思います。
追記: context使えます
context、this.$nuxt.context
で使えました。
- redirectは
this.$nuxt.context.redirect(path)
- resは
process.server
がtrueのときにthis.$nuxt.context.res
に入るので設定できる感じです