WP REST APIをReactでWordPressの記事一覧を表示させるスニペット [React版]

Reactのアイキャッチ画像

以前の記事では、jQueryとWP REST APIを使って記事一覧を表示するスニペットを紹介しましたが、今回はAPIでReactを使った記事一覧の方法について解説していきます。

関連記事 WP REST APIのJavaScriptで他のWordPressの記事をJSONで出力

かかかず
かかかず

また、ReactをWordPressへ導入する方法についても解説していきます。

WordPressのカスタマイズを行いたい方や、シングルページアプリケーションの運用に興味ある方は最後までご覧ください。

実装後のサンプル

早速ですが、実装後のサンプルです。

かかかず
かかかず

横型のカードで、6記事をAPIで出力しています。

記事のコンテンツをJavaScriptでレンダリングするので、速いです。

記事一覧を表示させるまでのざっくりとした手順

はじめに、記事一覧を表示させるまでの手順について解説します。ざっくりとしてますが、以下の通り4つのSTEPで完了です。

ReactをWordPressに読み込ませる

functions.phpに、React関連のファイルを読み込ませる設定を記述します。

JSのファイルにコードを記述

設定したJSのファイルに、WP REST APIで出力する内容をReactを使って記述します。

表示させたい位置にHTMLを記述

React で描画したい箇所を決めて、 DOM コンテナを追加する為にHTMLを記述します。

CSSをコピペ

最後に見た目を整えるCSSをコピペして完了です。

上記のように、STEP.1で functions.php をいじるのでバックアップをとってから行うようにしましょう。

注意点

この記事のスニペットは、基本コピペで実装できますが functions.php をいじります。

functions.phpは色々なことができるファイルですが、いじるのをミスってしまうと、WordPress全体が真っ白のエラーになってしまうこともあるので、注意が必要です。

バックアップをとってからやりましょう。

functions.phpをいじる場合、ftpで必ずバックアップを取ってから行い、テーマ本体ではなく子テーマの方に関数をコピペするようにしましょう。

実装の手順と具体的な方法

手順と方法

そんな概要を抑えつつ、ReactをWordPressに入れてみます。詳細の手順について解説していきます。

functions.phpにReact関連のファイルを読み込ませる

WordPressには、予めReactが同梱されています。それを使う為、functions.phpに以下のコードを記述します。

記述する時、Reactに使うjsのファイルが  my-react.js の場合、3行目の /js/my-script.js? の部分を例えば /js/my-react.js? に書き換えて記述します。

functions.php

add_action('wp_enqueue_scripts', function () {
// wp-elementを指定するとreact・react-domが入ってくる。
    wp_enqueue_script('my-script', get_theme_file_uri() . '/js/my-react.js?', ['wp-element'], '1.0.0', true);
});

読み込ませる方法は、以下のサイトを参考にさせていただきました。

外部リンク WordPress 5.0内でReactだけを利用する方法

読み込みが完了すると、<head>〜</head>の中に、以下2つのファイルが出力されていればOKです。※冒頭のパスの部分は、それぞれ異なります。

設定完了後のHTML

<script type='text/javascript' src='https://dubdesign.net/wp-includes/js/dist/vendor/react.min.js?ver=16.13.1' id='react-js'></script>
<script type='text/javascript' src='https://dubdesign.net/wp-includes/js/dist/vendor/react-dom.min.js?ver=16.13.1' id='react-dom-js'></script>

かかかず
かかかず

上記の2つが出力されていれば、準備はこれで完了です。

JSのファイルにコードを書く

STEP.1で本体に読み込ませるJSのファイルに、以下のコードをコピペします。

書き込む時は、Minifi(圧縮)して記述した方が少しでもファイルサイズを小さくできるので、そうしましょう。

コードを表示する

JavaScript

"use strict";

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      posts: []
    };
  }

  componentDidMount() {
    // Workaround for CORS issues on Codepen
    let noCorsURL = "https://dubdesign.net/"; // Endpoint you want to hit

    let endpoint = "posts?per_page=6&_embed"; // WP API base. Don't include the protocol.

    let dataURL = noCorsURL + "domain/wp-json/wp/v2/" + endpoint;
    fetch(dataURL).then(res => res.json()).then(res => {
      this.setState({
        posts: res
      });
    });
  }

  render() {
    let posts = this.state.posts.map(post => {
      return /*#__PURE__*/React.createElement("li", {
        key: post.id
      }, /*#__PURE__*/React.createElement("a", {
        href: post.link
      }, /*#__PURE__*/React.createElement("img", {
        src: post._embedded["wp:featuredmedia"][0].source_url
      }), /*#__PURE__*/React.createElement("div", {
        className: "card_textright"
      }, /*#__PURE__*/React.createElement("p", {
        className: "card_title",
        dangerouslySetInnerHTML: {
          __html: post.title.rendered
        }
      }), /*#__PURE__*/React.createElement("p", {
        className: "card_description",
        dangerouslySetInnerHTML: {
          __html: post.excerpt.rendered
        }
      }))));
    });
    return /*#__PURE__*/React.createElement("ul", {
      class: "wp-apicard_verticl"
    }, posts);
  }

}

ReactDOM.render( /*#__PURE__*/React.createElement(App, null), document.getElementById('app'));

表示させたい位置にHTMLを記述

React で描画したい箇所を決めて、 DOM コンテナを追加する為に以下のHTMLを記述すれば完了です。

HTML

<div id="app"></div>

CSSをコピペ

最後に見た目を整える以下のCSSをコピペして完了です。

コードを表示する

JavaScript

/* WP REST */
ul.wp-apicard_verticl {
    display: flex;
    list-style: none;
    border: none;
    padding: 0;
    flex-direction: column;
    flex-wrap: wrap;
}
ul.wp-apicard_verticl li {
    width: 100%;
    margin-bottom:25px;
}
ul.wp-apicard_verticl li a {
    display: flex;
    color: #313131;
    border-radius: 2px;
    background: #fff;
    box-shadow: 0 0 3px 0 rgb(0 0 0 / 12%), 0 2px 3px 0 rgb(0 0 0 / 22%);
    cursor: pointer;
    transition: 0.2s ease-in-out;
    padding: 5px;
}
ul.wp-apicard_verticl li a:hover {
    text-decoration: none;
    box-shadow: 0 15px 30px -5px rgb(0 0 0 / 15%), 0 0 5px rgb(0 0 0 / 10%);
    transform: translateY(-4px);
}
ul.wp-apicard_verticl li a img {
    width: 30%;
    margin-right: 3%;
    object-fit: cover;
    height: 190px;
}
.card_textright {
    width: 70%;
    display: flex;
    flex-direction: column;
    padding-right: 20px;
    justify-content: center;
}
.card_textright p {
    margin: 0;
}
p.card_title {
    font-size: 1.2rem;
    line-height: 1.56;
    color: #555;
    font-weight: 600;
    margin-bottom: 8px;
}
p.card_description {
    font-size: 0.8rem;
}
@media screen and (max-width: 767px) {
/* (ここにモバイル用スタイルを記述) */
ul.wp-apicard_verticl {
    padding-left: 2%;
    padding-right: 2%;
}
ul.wp-apicard_verticl li {
    margin-bottom: 20px;
}
ul.wp-apicard_verticl li a {
    flex-direction: column;
    padding: 0;
}
ul.wp-apicard_verticl li a img {
    width: 100%;
    object-fit: contain;
    height: auto;
    margin: 0;
}
.card_textright {
    width: 100%;
    padding: 20px 25px;
}
}

補足

記事中のJSコピペ用コードは、以下JSXをコンパイルしています。

コードを表示する

JSX

class App extends React.Component {

  constructor() {
    super();
    this.state = {
      posts: []
    }
  }
  
componentDidMount() {
  // Workaround for CORS issues on Codepen
  let noCorsURL = "https://dubdesign.net/"
  
  // Endpoint you want to hit
  let endpoint = "posts?per_page=6&_embed"
  
  // WP API base. Don't include the protocol.
  let dataURL = noCorsURL + "domain/wp-json/wp/v2/" + endpoint
  
  fetch(dataURL)
    .then(res => res.json())
    .then(res => {
      this.setState({
        posts: res
      })
    })
  }
  
  render() {
    
    let posts = this.state.posts.map((post) => {
      return <li key={post.id}>
        <a href={post.link}>
          <img src={post._embedded["wp:featuredmedia"][0].source_url}></img>
          <div className="card_textright">
          <p className="card_title" dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
          <p className="card_description" dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} />
          </div>
        </a>
      </li>
    })
    
    return (
      <ul class="wp-apicard_verticl">
        {posts}
      </ul>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));

参考サイト

参考React日本語公式サイトReact
カテゴリーのイラスト

同じカテゴリの記事一覧

ボタンの影