RIT Tech Blog

株式会社RITのエンジニアが知見を共有する技術ブログです。

Blitz.js 開発で実際に使った便利なQueryオプション

みなさん一度は「Blitz.js」というRailsにインスパイアされて作られたフルスタックReactフレームワークを聞いたことがあるのではないでしょうか。 触ったことがない方は是非触ってみてください。

https://blitzjs.com

本記事ではタイトルにあるように実際に使用したquery情報をまとめてみました。 また、Blitz.js は next + prismarailsのようにフルスタックなフレームワークを実現しているので、Blitzの理解のためにもprismaとnextを理解していると学習が捗ること間違いなしです。

ちなみにドキュメントにも以下の記載があるようにuseQueryはreact-queryを基に構築されているため、 自動キャッシュや、クエリ結果が古ければ再クエリを行うような機能も充実してます。

useQuery is built on react-query, so it automatically provides awesome features such as automatic caching and revalidation ※ 個人的にはキャッシュを有効活用することで表示パフォーマンスを上げれるのがreact-queryの1番のメリットだと感じている

補足として、それらの機能を利用する上でデフォルトの設定がされているクエリが複数存在しているため、想定外の結果になる場合はドキュメントに一度目を通して見ることをオススメします。

Out of the box, useQuery and the other query hooks are configured with aggressive but reasonable defaults. Sometimes these defaults can catch new users off guard or make learning/debugging difficult if they are unknown by the user.:

実際に使ったQueryオプション

refetchOnWindowFocus

  • 用途: window フォーカス時にデータが更新されてたらrefetchをしたい(true)・したくない時(false) window フォーカス時にrefetchをしたい(always) ※デフォルトはtrue

  • 使い方:

デフォルト
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnWindowFocus: true})

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnWindowFocus: false})

例2:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnWindowFocus: "always"})
  • 実際に起きたケース

    • form入力を行うページで別タブへ移動した後、form入力画面へ戻ってきたらrefetchが発生してしまい、入力していた情報が消えてしまった。
  • 実際のコード

const [project] = useQuery(getProject, projectId, {
  refetchOnWindowFocus: false,
  refetchOnReconnect: false,
})

公式ドキュメントに以下の記載があるように、上記のようなケースを防ぐ場合はrefetchOnWindowFocusrefetchOnReconnectをoptionとして付与してあげる必要があるとのことでした。

Stale queries will automatically be refetched in the background when the browser window is refocused by the user or when the browser reconnects. You can disable this using the refetchOnWindowFocus and refetchOnReconnect options in queries.

enabled

  • 用途 クエリAが処理完了次第、クエリQueryBをトリガーしたい

  • 使い方

const [user] = useQuery(getUser, { where: { id: props.query.id } })
const [projects] = useQuery(getProjects, { where: { userId: user.id } }, { enabled: user }))
  • 実際に起きたケース

    • 処理Aが完了後に確定する結果によって任意のデータを取得したかった。
  • 実際のコード

const projects = useQuery(
    getProjects,
    {
      where: getProjectsWhereParams,
      orderBy: {
        projectNumber: 'asc',
      },
    },
    {
      enabled: !!getProjectsWhereParams,  ← 
      refetchOnWindowFocus: false,
      refetchInterval: false,
    },
  );

以上が実際に開発で使ったQueryオプション達でした。 上記以外にも有用そうなオプションをいくつか公式ドキュメントから紹介したいと思います。 blitzjs.com

retry

  • 用途: クエリの実行結果が失敗だったら再クエリしたい

  • 使い方:

const [user] = useQuery(getUser, { where: { id: props.query.id } }, {retry: true})

retryOnMount

  • 用途: falseに設定するとエラーが含まれている場合、クエリはマウント時に再試行されない。 ※デフォルトはtrue

  • 使い方:

const [user] = useQuery(getUser, { where: { id: props.query.id } }, {retryOnMount: false})

retryDelay

  • 用途: retryするタイミングをミリ秒単位で設定できる(遅らせることができる)

  • 使い方:

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {retryDelay: 1000})

例2:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {retryDelay: attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)})

cacheTime

  • 用途: クエリのキャッシュ保持時間を設定できる(キャッシュしたくない場合にミリ秒単位で時間を指定することでキャッシュを廃棄できる) Infinityを設定すると廃棄しない

  • 使い方:

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {cacheTime:: 1000})

例2:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {cacheTime: Infinity})

refetchInterval

  • 用途: クエリをミリ秒単位で定期的に行える

  • 使い方:

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchInterval: 1000})

refetchIntervalInBackground

  • 用途: タブ/windowがバックグランド時にrefetchIntervalを行う

  • 使い方:

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchIntervalInBackground: true})

refetchOnMount

  • 用途: マウント時にデータが更新されてたらrefetchをしたい(true)・したくない時(false) マウント時にrefetchをしたい(always) ※デフォルトはtrue

  • 使い方:

デフォルト
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnMount: true})

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnMount: false})

例2:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnMount: "always"})

refetchOnReconnect

  • 用途: データが古くなっている場合、再接続時にrefetchしたい(true)・したくない時(false) 再接続時にrefetchしたい(always) ※デフォルトはtrue

  • 使い方:

デフォルト
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnReconnect: true})

例1:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnReconnect: false})

例2:
const [user] = useQuery(getUser, { where: { id: props.query.id } }, {refetchOnReconnect: "always"})