WordPress RestAPI を使ってフロントReactでヘッドレスCMSにする

WordPressで自作テーマを作るのは労力に対してできるものが微妙だなと思い、ヘッドレスCMSにしようと思いました。

スタイリングは一旦無視して機能だけ解説します。動作は次の動画のようになります。

WordPress の投稿をGETしてみる

Terminalで下記コマンドを実行してみましょう

curl -X GET "<https://your-wordpress-site.com/wp-json/wp/v2/posts>"

TerminalでJSONファイルは見づらいためPostmanを使うのがおすすめです。

React アプリをCreate

Terminal を開いて好きなディレクトリに移動して下記コマンドを実行します。

$ npx create-react-app my-ts-headless-cms-app --template typescript

投稿一覧ページの作成

srcディレクトリ内にPostList.tsxを作成します。

import React, { useState, useEffect } from 'react';
import axios from 'axios';

interface Post {
  id: number;
  title: { rendered: string };
}

const PostList: React.FC = () => {
  const [posts, setPosts] = useState<Post[]>([]);

  useEffect(() => {
    axios.get('https://your-wordpress-site.com/wp-json/wp/v2/posts')
      .then(response => {
        setPosts(response.data);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
      });
  }, []);

  return (
    <div>
      <h1>WordPress Post List</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title.rendered}</li>
        ))}
      </ul>
    </div>
  );
};

export default PostList;

App.tsx.を開いて書き換えましょう。

import React from 'react';
import './App.css';
import PostList from './PostList';

function App() {
  return (
    <div className="App">
      <PostList />
    </div>
  );
}

export default App;

一旦ここで動作確認してみましょう!Termialを開いて

$ npm start

うまく起動できましたか??

できたら詳細ページを作っていきましょう!

詳細ページの作成

axis のインストールをします

$ npm i axis

srcディレクトリ内に、PostDetail.tsx を作成します。

import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import axios from 'axios';

interface Post {
  id: number;
  title: { rendered: string };
  content: { rendered: string };
}

const PostDetail: React.FC = () => {
  const { postId } = useParams<{ postId: string }>();
  const [post, setPost] = useState<Post | null>(null);

  useEffect(() => {
    axios.get(`https://your-wordpress-site.com/wp-json/wp/v2/posts/${postId}`)
      .then(response => {
        setPost(response.data);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
      });
  }, [postId]);

  if (!post) {
    return <div>Loading...</div>;
  }

  return (
    <div>
      <h1>{post.title.rendered}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />
    </div>
  );
};

export default PostDetail;

react-router-dom をインストールしましょう!

$ nom install react-router-dom

App.tsx を書き換えます

import React from 'react';
import { BrowserRouter, Route } from 'react-router-dom';

import PostList from './PostList';
import PostDetail from './PostDetail';
import './App.css';

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <div className="Contents">
            <Route index path="/" element={<PostList/>} />
            <Route index path="/post/:postId" element={<PostDetail/>} />
        </div>
      </div>
    </BrowserRouter>
  );
}

export default App;

リストから詳細への遷移を作る

PostList.tsx を下記のように書き換えます。

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { Link } from 'react-router-dom';

interface Post {
  id: number;
  title: { rendered: string };
}

const PostList: React.FC = () => {
  const [posts, setPosts] = useState<Post[]>([]);

  useEffect(() => {
    axios.get('https://your-wordpress-site.com/wp-json/wp/v2/posts')
      .then(response => {
        setPosts(response.data);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
      });
  }, []);

  return (
    <div>
      <h1>WordPress Post List</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>
            {/* 詳細ページへのリンク */}
            <Link to={`/post/${post.id}`}>{post.title.rendered}</Link>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default PostList;

coiai.netでは案件受付中です。
Vtuber、建築モデリング、EC構築、ネイティブアプリ制作、制服の制作(実は縫製業もメイン)、Vision Pro向けアプリ etc…
様々な制作開発を行っています。

ご気軽にご相談ください!

コイアイちゃんのアバター

この記事を書いたのは


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


Top
Blog
Works
contact