目標
本記事はReactでアプリを作成することが目的ではなく、Reactで作成したものをWordPress内に取り入れることが目標となっております。
そのため、Reactのコンポーネント化等、最適化等はしておりません。
(TypeScriptも導入しておりません)
viteを使用して新規Reactアプリを作成する
viteを使用して新規Reactアプリの作成
yarn create vite
新規アプリ作成方法が分からない方は以下参考にしてみて下さい。
https://ja.vitejs.dev/guide/
(今回はTypeScript選択せずに、 JavaScriptを選択しました)
上記コマンド実行してアプリを起動してみます。
以下のような画面が表示できたら成功です!
作成したReactアプリを不要なデータ削除し何もない状態にする
src/App.jsx
の内容を綺麗に削除します。
一旦テストと表示させておきます。
WordPressの記事をJSON表示させてみる
実はWordPressは何もしなくてもJSONデータを生成して表示しています。。
https://{ドメイン}/wp-json/wp/v2/{表示したい記事種類等}
とすると確認できます。
実際に私のブログサイトで試してみます。
https://just-a-mother.com/wp-json/wp/v2/posts
私のブログは全て既存の投稿を使用しているの記事の種類はpostです。
ここがカスタム投稿タイプや固定ページなどになると変わってきます。
詳しくはいろいろあるので、自分が取得したい記事内容など調べてみて下さい。
上記にアクセスすると以下のようなJSONデータを確認することができます。
上記のように成形されずただの文字列っぽく見えてしまう人はChromeの拡張機能の「JSON Viewer」
などを入れたら見やすくなります!
WordPressの記事をReatで取得してみる
apiを使用してHTTPリクエストするために今回はaxiosをインストールして使用します。
yarn add axios
axios以外にもいろいろあるので、良ければ調べてみて下さい。
import { useEffect, useState } from "react";
import "./App.css";
import axios from "axios";
function App() {
const [posts, setPosts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const URL = "https://just-a-mother.com/wp-json/wp/v2/posts";
axios.get(URL).then((res) => {
setPosts(res.data);
setIsLoading(false);
});
}, []);
console.log("posts", posts);
return (
<>
<div>テスト</div>
</>
);
}
export default App;
上記のように最低限の記述ですが、コンソールログに取得した記事を出してみます。
ちゃんと10件分の記事が取得できました
ですが、10件しか取得できていないですね。。
調べたところ、デフォルトで10件、パラメータ付きで100件までとありましたので、
const URL = "https://just-a-mother.com/wp-json/wp/v2/posts";
↓
const URL = "https://just-a-mother.com/wp-json/wp/v2/posts?per_page=100";
としたところ、無事に全件取得できました!
(私のブログには28件しか記事がないんで、、、)
もう一つ、今回は記事に設定してあるタグ情報を取得します。
下記でWordPressの記事投稿で設定しているタグ情報を取得できました。
const TAGS_URL = "https://just-a-mother.com/wp-json/wp/v2/tags";
axios.get(TAGS_URL).then((res) => {
setTags(res.data);
});
こんな感じで取得できています!
上記getするコードを追記しても良いのですが、
二つのapiでまとめてgetしたいのでPromise.allに記述を変更します。
axios.get(POSTS_URL).then((res) => {
setPosts(res.data);
});
axios.get(TAGS_URL).then((res) => {
setTags(res.data);
setIsLoading(false);
});
// 以下に書き換える ↓
useEffect(() => {
Promise.all([axios.get(POSTS_URL), axios.get(TAGS_URL)]).then(
([postsResponse, tagsResponse]) => {
setPosts(postsResponse.data);
setTags(tagsResponse.data);
setIsLoading(false);
}
);
まず、タグリストを表示させます。
下記でタグリストが表示されました!
(CSSは当ててます)
{isLoading ? null : (
<div className="">
<ul className="tag-list">
{tags.map((tag, i) => (
<li key={i} className="tag-item">
{tag.name}
</li>
))}
</ul>
</div>
)}
クリックしたタグが付与されている記事を下へ表示させる
次にタグボタン下に選択したタグに関連する記事を表示させてみます。
const handleFiler = useCallback(
(id) => {
setFilteredPosts(posts.filter((post) => post.tags.includes(id)));
},
[posts]
);
上記フィルターする関数を作成します。
ulの方も以下のように修正します。
<ul className="tag-list">
{tags.map((tag, i) => (
<li
key={i}
className="tag-item"
onClick={() => handleFiler(tag.id)} // clickしてidが取得できるように追記
>
{tag.name}
</li>
))}
</ul>
<ul className="post-list">
{filteredPosts.map((post, i) => (
<li key={i} className="post-item">
<a href={post.link} className="post-link">
{post.title.rendered}
</a>
</li>
))}
</ul>
これでクリックしたら該当タグが付与されてた記事が下へ表示できるようになりました。
Reactアプリをビルドする
上記までで簡単ではありますが、Reactを使用したアプリが完成できました。
ビルドします。
ビルドするとdistディレクトリができました。
dist/assets/index--1kmMQDK.css
dist/assets/index-Zr6b2y_5.js
この二つのソースを使用します!
WordPressに組み込んでみる
先ほどビルドしたソースを使用します。
オリジナルテーマに組み込む
例えば特定の固定ページに組み込みたいとします。
page-{記事slug}.php
<!-- 記事ページ -->
<?php get_header(); ?>
<section class="main_post">
<div id="app"></div> //ここにReact組み込む
<!-- サイトバー -->
<?php get_sidebar(); ?>
</section>
<?php get_footer(); ?>
記事のPHPテンプレートの組み込みたい場所に
<div id="app"></div>
を入れます。
そして、このページに先ほどビルドしたjsファイルとCSSファイルを読み込みします。
もちろん、サーバーへjsファイル、cssファイルをアップすることもお忘れなく!
有料テーマを使用しつつ、特定ページに組み込む
私はブログ用にSWELL(有料テーマ)を使用しています。
この特定の固定ページに組み込みたいと思います。
カスタムHTMLを入力できる枠を出し、そこに
<div id="app"></div>
を記載します。
その下のこのページに読み込むCSSとJSという箇所に先ほどビルドしたファイルをコピぺします。
そして更新&公開
ちゃんと表示できました!
なぜid="app"??
Reactアプリを組み込みしたい箇所には
<div id="app"></div>
としたらそこにReactで作成したアプリが表示されました。
なぜid="app"なのか?他のidだとダメ??
Reactアプリを生成する際の大元の
index.htmlにid="app"としています。
そして、そこに
src/main.jsxにて
document.getElementById("app")
とid="app"にをレンダーしているのでid="app"にしないといけません。
ここのidを例えばid="myApp"とかにしていれば、id="myApp"を使用しないといけません。
なので、どんな時でもid="app"ではないということは気をつけましょう。
上記が実際に作成したReactアプリを組み込みしたページとなります。
## 補足
最終的にapp.jsxのソースはこちらです。
import { useEffect, useState, useMemo, useCallback } from "react";
import "./App.css";
import "./reset.css";
import axios from "axios";
const POSTS_URL = "https://just-a-mother.com/wp-json/wp/v2/posts?per_page=100";
const TAGS_URL = "https://just-a-mother.com/wp-json/wp/v2/tags";
function App() {
const [posts, setPosts] = useState([]);
const [tags, setTags] = useState([]);
const [filteredPosts, setFilteredPosts] = useState([]);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
Promise.all([axios.get(POSTS_URL), axios.get(TAGS_URL)]).then(
([postsResponse, tagsResponse]) => {
setPosts(postsResponse.data);
setTags(tagsResponse.data);
setIsLoading(false);
}
);
}, []);
const handleFiler = useCallback(
(id) => {
console.log("id", id);
setFilteredPosts(posts.filter((post) => post.tags.includes(id)));
},
[posts]
);
return (
<>
{isLoading ? null : (
<div className="">
<h2 className="title">興味がある分野を選んで下さい</h2>
<ul className="tag-list">
{tags.map((tag, i) => (
<li
key={i}
className="tag-item"
onClick={() => handleFiler(tag.id)}
>
{tag.name}
</li>
))}
</ul>
<ul className="post-list">
{filteredPosts.map((post, i) => (
<li key={i} className="post-item">
<a href={post.link} className="post-link">
{post.title.rendered}
</a>
</li>
))}
</ul>
</div>
)}
</>
);
}
export default App;
以上です。
WordPressや静的サイトに気軽にReactアプリを組み込みして見て下さいね!