microCMSのプレビュー機能をGatsby.jsで使う


Gatsby.jsは言わずと知れたReact製の静的サイトジェネレーターですが、ビルド時にページを生成するという性質ゆえに、microCMSのプレビュー機能を使うにはひと工夫必要だったので共有したいと思います。
この機能をご存知の方はコードの部分からご覧ください。

microCMSの記事プレビュー機能について

microCMSのプレビュー機能について少し説明しておくと、記事執筆画面で

公開ボタンの左にある画面プレビューを押した時に、執筆中の記事が実際にはどのように表示されるか確認できる機能です。仕組みとしては、

  • 「画面プレビュー」をクリック
  • 予め設定しておいたURLの変数部分(contentsIdとdraftKey)がクリックした記事のものに置き換えられたURLにアクセス

という感じです。
詳しくはhttps://microcms.io/blog/draftkey_and_preview/ に掲載されています。

 何が問題でどうしたらいいのか?

この機能をGatsbyで使用する時、考えなければならないのは、Gatsby.jsの記事データは基本ビルド時に生成された物なので、
「画面プレビュー」クリック時に送られてきたcontentIddraftKeyを基に記事データをリアルタイムに取得して、表示する仕組みを作らないといけない。ということです。

 ということでコード

前置きはそのくらいにしてコードはこのようになりました。

pages/previewPage.jsx
import React, { useState, useEffect } from "react";
import { getSearchParams } from "gatsby-query-params";
//...その他コンポーネントなど

function previewPage() {
  //microCMS側に設定するurlはhttps://xxxxxx.com/previewPage/?contentId={CONTENT_ID}&draftKey={DRAFT_KEY}みたいな感じ
  const queryParams = getSearchParams();

  //queryParamsには
  //{contentId:"xxxx",
  //draftKey:"xxxx"}
  //というようなデータが入ります。

  const contentId = queryParams.contentId;
  const draftKey = queryParams.draftKey;

  const [postData, setPostData] = useState(null);//最初、postDataにはnullが入ります。

  useEffect(() => {
    if (!postData) {
      fetch(
        `https://xxxxxxxxx.microcms.io/api/v1/blogs/${contentId}?draftKey=${draftKey}`,
        {
          headers: {
            "X-API-KEY": "xxxxxxx-xxxx-xxxxx-xxxx-xxxxxxxx",
          },
        }
      )
        .then((response) => {
          if (response.ok) {
            return response.json();
          }
        })
        .then((json) => {
          postData = setPostData(json);//ここで、postDataに取得したコンテンツが格納されます。
        });
    } else {
      return function cleanup() {
        console.log("done");
      };
    }
  });
  return (
        <div
          dangerouslySetInnerHTML={{
            __html: postData ? postData.sentence : "",
          }}
        ></div>
  );
}

export default previewPage;

このようなページを作成することで、アクセスした時にurlクエリパラメータの情報を基にコンテンツをとってきてくれます。
以下、詳しく説明していきます。

API部分について

microCMSはPOSTとGETのAPI-KEYが違うのでGETのAPIが露出しても大して問題はないですが、なんとなく気持ちが悪いので、
X-API-KEY: "xxxxx-xxxx"としている部分とmicroCMSのurl部分は実際には環境変数に置き換えるのが望ましいです。環境変数の使い方に関してはこちらの記事の中でも説明しているので是非ご覧ください。

gatsby-query-paramsについて

2行目に登場するgatsby-query-paramsこちらです。
使用するにはターミナルでnpm i gatsby-query-paramsしてください。

コメントアウト部分にもありますが、getSearchParamsによって、urlクエリパラメータの情報をqueryParamsにオブジェクト形式で格納しています。

useState useEffectについて

これらはReactのhookで、詳しい説明はこちらにあります。
useEffectの中で、↑で取得したクエリパラメータを基にmicroCMSにデータを取得しにいき、取得できたら、それをpostDataに格納しています。

responce.okについて

これがないとmicroCMSのレスポンスが404の時(useStateがnullの間)返ってくる空文字列""を処理しようとしてしまい、jsonオブジェクトでないのでエラーが出てしまいます。

レンダリング部分について

return()内のpostData ? postData.sentence : ''としている部分で、postDataに↑でとってきた記事データが格納されたら、それが表示されるようになっています。postData.sentenceと書いていますが、sentenceの部分はmicroCMSで定義した表示したいデータのフィールドIDが入ります。レンダリング部分は他の記事ページのレイアウトに合わせて、煮るなり焼くなりしてください!

まとめ

サイトを見にきた人が、/今回作ったページと打つとアクセスできてしまいますが、contentsIdとdraftKeyがないので何も表示されないですし、一応は問題ないと思います。

色々と改善の余地はありそうですが、とりあえずこれで投稿前の記事をプレビューで確認できるので、是非活用してみてください!