TwitterFacebookHatena

WordPress GraphQL と Next.js を使ったデータ取得

WordPress GraphQL API に接続する

WordPress から、Next.js に乗り換えたいけど、WordPress の記事数が多すぎて、データを移行するのが大変という場合は、WordPress の GraphQL API を使って、データを取得することができます。GraphQL は、WordPress のプラグインをインストールすることで、WordPress からデータを取得することができるようになります。

Next.js と TypeScript を使って、WordPress の GraphQL API に接続してデータを取得してみましょう。まずは、WordPress に GraphQL プラグインをインストールして有効化し、API エンドポイントが利用可能になることを確認してください。続いて、apollo-client および関連パッケージをプロジェクトにインストールします。

npm install @apollo/client graphql

次に、Apollo Client のインスタンスを作成し、WordPress の GraphQL API エンドポイントを指定します。

// lib/apolloClient.ts
import { ApolloClient, InMemoryCache } from '@apollo/client'

const apolloClient = new ApolloClient({
  uri: 'https://your-wordpress-url/graphql',
  cache: new InMemoryCache(),
})

export default apolloClient

クエリを作成してデータを取得する

次に、GraphQL クエリを作成し、WordPress からデータを取得します。ここでは、投稿データを取得するクエリを定義してみます。

// graphql/queries.ts
import { gql } from '@apollo/client'

export const GET_POSTS = gql`
  query GetPosts {
    posts {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`

データを Next.js のページで表示する

次に、getStaticProps 関数を使って Next.js のページでクエリを実行し、取得したデータを表示します。

// pages/index.tsx
import { GetStaticProps } from 'next'
import { useQuery } from '@apollo/client'
import apolloClient from '../lib/apolloClient'
import { GET_POSTS } from '../graphql/queries'

type Post = {
  id: string
  title: string
  content: string
}

type Props = {
  initialPosts: Post[]
}

const Home = ({ initialPosts }: Props) => {
  const { data } = useQuery(GET_POSTS, {
    ssr: false,
  })

  const posts = data?.posts.edges.map(({ node }: any) => node) || initialPosts

  return (
    <div>
      {posts.map((post: Post) => (
        <div key={post.id}>
          <h2>{post.title}</h2>
          <div dangerouslySetInnerHTML={{ __html: post.content }} />
        </div>
      ))}
    </div>
  )
}

export const getStaticProps: GetStaticProps = async () => {
  const { data } = await apolloClient.query({
    query: GET_POSTS,
  })

  const initialPosts = data.posts.edges.map(({ node }: any) => node)

  return {
    props: {
      initialPosts,
    },
    revalidate: 60, // 60 seconds
  }
}

export default Home

ここでは、getStaticProps 関数を使用して、ビルド時にデータを取得し、静的ページを生成しています。revalidate オプションにより、60 秒ごとにページを再生成することでデータが更新されるようになります。また、useQuery を使ってクライアントサイドでデータを取得し、既存のデータがあればそれを表示します。

カスタムフックを作成してデータ取得を簡潔にする

データ取得のロジックをカスタムフックにまとめることで、コンポーネントがすっきりとして可読性が向上します。

まず、カスタムフックを定義しましょう。

// hooks/usePosts.ts
import { useQuery } from '@apollo/client'
import { GET_POSTS } from '../graphql/queries'

type Post = {
  id: string
  title: string
  content: string
}

export const usePosts = (initialPosts: Post[]) => {
  const { data } = useQuery(GET_POSTS, {
    ssr: false,
  })

  const posts = data?.posts.edges.map(({ node }: any) => node) || initialPosts

  return posts
}

次に、pages/index.tsx でカスタムフックを使用します。

// pages/index.tsx
import { GetStaticProps } from 'next'
import apolloClient from '../lib/apolloClient'
import { GET_POSTS } from '../graphql/queries'
import { usePosts } from '../hooks/usePosts'

type Post = {
  id: string
  title: string
  content: string
}

type Props = {
  initialPosts: Post[]
}

const Home = ({ initialPosts }: Props) => {
  const posts = usePosts(initialPosts)

  return (
    <div>
      {posts.map((post: Post) => (
        <div key={post.id}>
          <h2>{post.title}</h2>
          <div dangerouslySetInnerHTML={{ __html: post.content }} />
        </div>
      ))}
    </div>
  )
}

export const getStaticProps: GetStaticProps = async () => {
  const { data } = await apolloClient.query({
    query: GET_POSTS,
  })

  const initialPosts = data.posts.edges.map(({ node }: any) => node)

  return {
    props: {
      initialPosts,
    },
    revalidate: 60,
  }
}

export default Home

これで、Next.js と TypeScript を使って WordPress の GraphQL API を使ってデータを取得し、表示する方法が完成しました。カスタムフックを利用することで、コンポーネント内でのデータ取得のロジックが簡潔になり、再利用性が向上します。

WordPress GraphQL と Next.js を使ったデータ取得