【Gatsby.js + TypeScript】useStaticryQueryの使い方

June 28, 2023

top画像

はじめに

Gatsby.js は本当に便利な静的サイト生成ツールです。 便利なフレームワークではありますが、個人的に一番やっかいなのは QrapgQL ではないでしょうか。 使えると便利なのですが他で触る機会が少ないので理解するまでに結構時間がかかります。 その中で今回は useStaticQuery の使い方を書いていきますので何かの参考になればと思います。 公式ドキュメントはこちらです。

やりたいこと

コンポーネントに GraphQL で取得したデータを渡すこと

開発環境

  • Gatsby.js
  • TypeScript
  • emotion(css-in-js のフレームワーク)

まず StaticQuery とは

公式ドキュメントより

Gatsby v2 introduces StaticQuery, a new API that allows components to retrieve data via a GraphQL query.

Gatsby のバージョン 2 より追加された新しい API でコンポーネントが GraphQL 経由でデータを取得できるようになります。

なぜこれを使うかというと今までの記述だとページ生成時しかデータを渡すことができずにいて、レイアウトページ等の親コンポーネントから順々にデータを渡す必要がありました。 階層が浅ければいいのですが、何階層も下のコンポーネントにデータを渡すのは一苦労でした。

それを解決するのが StaticQuery です。

つまりどこのコンポーネントでも QraphQL からデータが取れるようになるということです。 さらに StaticQuery の書き方は複数あって、今回はフックである useStaticQuery を使用しています。

使い方

import する

useStaticQuery を使用できるようにまず import します。

import { useStaticQuery, graphql } from "gatsby"

GraphQL でデータを取得する

GraphQL で取得したデータを変数 data に格納します。 色々やり方はあると思いますがここでは filter で images フォルダにある File を取得しています。 これだけだと画像データは複数取得できてしまうので、コンポーネントに汎用性を持たせるために後の処理で画像を限定します。

const data: ImageQuery = useStaticQuery(
  graphql`
    query Image {
      allFile(filter: { sourceInstanceName: { eq: "images" } }) {
        edges {
          node {
            id
            relativePath
            sourceInstanceName
            childImageSharp {
              id
              fixed(width: 200, height: 200) {
                base64
                width
                height
                src
                srcSet
                originalName
              }
            }
          }
        }
      }
    }
  `
)

画像の限定

親コンポーネントでこのように Image コンポーネントを呼び出します。

<Image name="avater-face.png" />

name に画像のファイル名を指定します。

Image コンポーネント側ではこの props により find メソッドでファイル名を比較します。

const edge = data.allFile.edges.find(
  edge => edge.node.relativePath == props.name
)

コンポーネントの export 最後に return で gatsby-images の Img コンポーネントを返せば完了です。

return <Img fixed={edge.node.childImageSharp.fixed} />

コード全体(Image コンポーネント)

import * as React from "react"
import { useStaticQuery, graphql } from "gatsby"
import { ImageQuery } from "../../types/graphql-types"
import Img from "gatsby-image"

interface Props {
  name?: string
}

const Image: React.FC<Props> = props => {
  const data: ImageQuery = useStaticQuery(
    graphql`
      query Image {
        allFile(filter: { sourceInstanceName: { eq: "images" } }) {
          edges {
            node {
              id
              relativePath
              sourceInstanceName
              childImageSharp {
                id
                fixed(width: 200, height: 200) {
                  base64
                  width
                  height
                  src
                  srcSet
                  originalName
                }
              }
            }
          }
        }
      }
    `
  )
  const edge = data.allFile.edges.find(
    edge => edge.node.relativePath == props.name
  )
  return <Img fixed={edge.node.childImageSharp.fixed} />
}
export default Image

まとめ

gatsby.js で画像を表示させる処理は他のものに比べてかなりめんどくさいですが、このように汎用コンポーネントにしてやればそれほどめんどくさくなくなります。 ただ、幅や高さの指定をするのが結構めんどくさいのでその辺もっといい感じに書けるようになれるとさらによくなると思います。


Profile picture

Written by Mittsu
ベンチャー企業のしがないエンジニア。趣味はサッカーとTCG.

© 2024