Help us understand the problem. What is going on with this article?

Nuxt2.12.0で新しくなったfetchについて

Nuxt2.12.0でfetch methodが新しくなりました。

https://github.com/nuxt/nuxt.js/releases/tag/v2.12.0

...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側ではこのように表示を出し分けることができます。

Frame 2.png

イメージを図にするとこんな感じでしょうか。fetchはmount前(SSR含む)とmethodを叩いたときに呼ばれます。pageComponentではないので、propの値に応じてfetchするようなコンポーネントも作りやすいと思います。

propの値でfetchする例

image.png

image.png

image.png

https://twitter.com/Atinux/status/1106201847734456320?s=20

古いツイートなので$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--)
}

https://github.com/nuxt/nuxt.js/blob/1f3c3ad9f3f0da93e1fb59aa0bed4be768f2f1fe/packages/vue-app/template/mixins/fetch.client.js#L55-L79

この辺の処理は上記のコードにある通り、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

Nuxt 3: Context changes

ですがRFCにあるように将来的には this.$ctx が生えるようになるようです。
こちらを使うことでasyncDataの役割はfetchでできるようになっていくと思います。

追記: context使えます

https://twitter.com/Atinux/status/1240193656969101312

context、this.$nuxt.context で使えました。

  • redirectは this.$nuxt.context.redirect(path)
  • resは process.server がtrueのときに this.$nuxt.context.res に入るので設定できる感じです
miyaoka
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした