以前の記事では、jQueryとWP REST APIを使って記事一覧を表示するスニペットを紹介しましたが、今回はAPIでReactを使った記事一覧の方法について解説していきます。
関連記事 WP REST APIのJavaScriptで他のWordPressの記事をJSONで出力
また、ReactをWordPressへ導入する方法についても解説していきます。
WordPressのカスタマイズを行いたい方や、シングルページアプリケーションの運用に興味ある方は最後までご覧ください。
目次
実装後のサンプル
早速ですが、実装後のサンプルです。
横型のカードで、6記事をAPIで出力しています。
記事のコンテンツをJavaScriptでレンダリングするので、速いです。
記事一覧を表示させるまでのざっくりとした手順
はじめに、記事一覧を表示させるまでの手順について解説します。ざっくりとしてますが、以下の通り4つのSTEPで完了です。
functions.phpに、React関連のファイルを読み込ませる設定を記述します。
設定したJSのファイルに、WP REST APIで出力する内容をReactを使って記述します。
React で描画したい箇所を決めて、 DOM コンテナを追加する為にHTMLを記述します。
最後に見た目を整えるCSSをコピペして完了です。
上記のように、STEP.1で functions.php
をいじるのでバックアップをとってから行うようにしましょう。
注意点
この記事のスニペットは、基本コピペで実装できますが functions.php
をいじります。
functions.php
は色々なことができるファイルですが、いじるのをミスってしまうと、WordPress全体が真っ白のエラーになってしまうこともあるので、注意が必要です。
実装の手順と具体的な方法
そんな概要を抑えつつ、ReactをWordPressに入れてみます。詳細の手順について解説していきます。
functions.phpにReact関連のファイルを読み込ませる
WordPressには、予めReactが同梱されています。それを使う為、functions.phpに以下のコードを記述します。
記述する時、Reactに使うjsのファイルが my-react.js の場合、3行目の /js/my-script.js?
の部分を例えば /js/my-react.js?
に書き換えて記述します。
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です。※冒頭のパスの部分は、それぞれ異なります。
<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(圧縮)して記述した方が少しでもファイルサイズを小さくできるので、そうしましょう。
コードを表示する
"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を記述すれば完了です。
<div id="app"></div>
CSSをコピペ
最後に見た目を整える以下のCSSをコピペして完了です。
コードを表示する
/* 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をコンパイルしています。
コードを表示する
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