PowerCMS Xに搭載されている「サイト内全文検索機能(SearchEstraierプラグイン)」のドキュメントで「レコメンドAPIアプリケーション」が紹介されており、APIレスポンスからお勧めページを表示させるビューのサンプルがjQueryで記述されています。これをReactで書き直してみました。意図は「jQueryのコードは単にJSONを取ってきてHTMLを組み立てているだけで、難しいことは何もやっていないことの証明」です。Reactは色々作法があってとっつきにくいかもしれませんが、UIとロジックを分離することができてコードが分かりやすいはずです。このようなReactコンポーネントを配布したりプロジェクト間で流用したりすると制作が楽になるのでは?、とも考えています。
本来ならばCSSもコンポーネント内に記述して管理するのですが、話がややこしくなるので一旦スコープ外とします。作業ディレクトリでnpm create vite@latest
を実行すると容易に書き始めることができます。
記事を表示するEntryListItemコンポーネント
単に1つの記事データを表示するだけのコンポーネントです。EntryListItem.jsxに記述します。このファイルを書き換えることで見栄え(HTML)が容易に変更できます。
import dayjs from "dayjs";
function EntryListItem({ entry }) {
const publishedOn = dayjs(entry.cdate).format('YYYY-MM-DD HH:mm')
return (
<li className="recommend-list_item">
<div className="d-flex">
<div className="recommend-thumbnail">
{entry.thumbnail_square ? (
<img src={entry.thumbnail_square} alt="" width="50" height="50" />
) : (
<img src="/website/images/no-image.png" alt="" width="50" height="50" />
)}
</div>
<div className="recommend-link-wrapper">
<a href={entry.uri} className="recommend-link">{entry.title}</a>
<span className="recommend-date">公開日 : {publishedOn}</span>
</div>
</div>
</li>
)
}
export default EntryListItem;
記事を取得して表示処理を呼び出すRecommendコンポーネント
レコメンドAPIアプリケーション(pt-recommend-api.php)から記事データを取得し、それをループして記事データを表示するEntryListItemコンポーネントを呼び出すコンポーネントです。Recommend.jsxに記述します。
import { useCallback, useEffect, useState } from 'react'
import EntryListItem from './EntryListItem';
function Recommend() {
const [similarEntries, setSimilarEntries] = useState([]); // 関連記事を保存するstate変数
const [interestEntries, setInterestEntries] = useState([]); // おすすめ記事を保存するstate変数
const currentUrl = location.href;
// 記事の取得
const fetchEntries = useCallback(async () => {
let json;
try {
const response = await fetch(`<アプリのURL>/plugins/SearchEstraier/app/pt-recommend-api.php?type=both&limit=${limit}&url=${currentUrl}`);
json = await response.json();
} catch (e) {
return;
}
// 関連記事をstate変数にセット
if (json.similar) {
setSimilarEntries(json.similar);
}
// おすすめ記事をstate変数にセット
if (json.interest) {
setInterestEntries(json.interest);
}
}, [currentUrl]);
// APIと同期させるためのReactフック
useEffect(() => {
fetchEntries(); // 記事の取得を実行
}, [fetchEntries])
return (
<>
{similarEntries.length > 0 && (
<div id="similar-list-wrapper">
<h2>関連性の高いページ</h2>
<ul className="list-unstyled ml-0 recommend-list">
{similarEntries.map((entry) => (
<EntryListItem key={entry.object_id} entry={entry} />
))}
</ul>
</div>
)}
{interestEntries.length > 0 && (
<div id="interest-list-wrapper">
<h2>あなたへのお勧め</h2>
<ul className="list-unstyled ml-0 recommend-list">
{interestEntries.map((entry) => (
<EntryListItem key={entry.object_id} entry={entry} />
))}
</ul>
</div>
)}
</>
)
}
export default Recommend;
指定のHTML要素内に描画
ここまで記述したコードを基に、<div id="recommend_app"></div>
内に記事リストを表示する処理です。main.jsxに記述します。
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import Recommend from './Recommend.jsx'
createRoot(document.getElementById('recommend_app')).render(
<StrictMode>
<Recommend />
</StrictMode>,
)
補足
Viteで開発する際はhttp://localhost:5173
のようなURLで表示確認をすると思うので、PowerCMS Xの環境変数「api_allowed_origin」でオリジンhttp://localhost:5173
を許可する必要があります。