article

Thursday, November 21, 2024

React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS

React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS

React JS
https://react.dev/learn/start-a-new-react-project

npx create-next-app@latest
npx create-react-app@latest {project name}
Create Project
C:\react-js>npx create-react-app@latest my-app
Run
C:\react-js\my-app> npm start

Install tailwindcss https://tailwindcss.com/docs/guides/create-react-app
npm install -D tailwindcss
npx tailwindcss
init Install

react-router-dom
https://www.npmjs.com/package/react-router-dom Install axios
src\App.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//src\App.js
import { BrowserRouter, Routes, Route } from "react-router-dom"; //npm i react-router-dom https://www.npmjs.com/package/react-router-dom
import Home from "./elements/Home";
import ViewPage from "./elements/ViewPage";
 
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/posts/:slug" element={<ViewPage />} />
      </Routes>
    </BrowserRouter>
  );
}
 
export default App;
src\elements\Home.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//src\elements\Home.js
import React  from 'react';
import Posts from './Posts'
import { Suspense } from "react";
import { IoSearch } from "react-icons/io5"; //https://www.npmjs.com/package/react-icons npm install react-icons --save
 
function Home() {
 
  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center">
        <div className="flex items-center justify-between gap-1 mb-5">
            <h1 className="text-4xl font-bold">React.js + WordPress Load Posts with Featured Image and View Single Page | Tailwind CSS</h1>
        </div>
        <div className="overflow-x-auto py-10">
            <div className="mb-2 w-full text-right">
                <div className="relative flex flex-1">
                <input
                    type="text"
                    className="w-full border border-gray-200 py-2 pl-10 text-sm outline-2 rounded-sm"
                    placeholder="Search..."
                />
                <IoSearch className="absolute left-3 top-2 h-5 w-5 text-gray-500" />
                </div>
            </div>
            <Suspense fallback="Loading...">
                <Posts/>
            </Suspense>
        </div>
    </div>
  )
}
 
export default Home
src\elements\Posts.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//src\elements\Posts.js
import React, { useEffect, useState } from 'react';
 
export default function Posts() {
    const [posts, setPosts] = useState([]);
    useEffect(() => {
        async function loadPosts() {
            const response = await fetch('http://localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed');
            if(!response.ok) {
                // oups! something went wrong
                return;
            }
     
            const posts = await response.json();
            setPosts(posts);
        }
     
        loadPosts();
   }, [])
  return (
      <div className="grid md:grid-cols-3 gap-5 mt-10">
        {posts.map((post, index) => (
          <div key={index} className="max-w-sm border border-gray-200 rounded-md shadow">
            <div className="relative aspect-video">
              <img src={post._embedded["wp:featuredmedia"][0].media_details.sizes.full.source_url}
                alt={post.title.rendered}
                fill
                priority
                sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
                className="rounded-t-md object-cover"/>
            </div>
            <div className="p-5">
              <h1>
                <a
                  href={`/posts/${post.slug}`}>
                  {post.title.rendered}
                </a>        
              </h1>
            </div>
          </div>
        ))}
      </div>
 );
}
src\elements\ViewPage.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//src\elements\ViewPage.js
import React from 'react';
import { useEffect, useState } from 'react';
import { useParams } from "react-router-dom";
 
export default function Posts() {
    const {slug}=useParams();
 
    const [posts, setData] = useState(null);
 
    useEffect(()=>{
        fetchPost();
    },[slug]);
      
    const fetchPost=async()=>{
        try{
          const response = await fetch("http://localhost:8888/cairocoders/wp-json/wp/v2/posts?_embed&slug="+slug);
            if(!response.ok) {
                // oups! something went wrong
                return;
            }
 
            const posts = await response.json();
            //console.log(posts);
            setData(posts);
        }catch(err){
            console.log("Something Wrong");
        }
    }
 
    return (
    <div className="min-h-screen flex items-center justify-center bg-slate-100">
      <div className="bg-white rounded-sm shadow p-8">
        {posts && posts.map((post, index) => (
        <div key={index}>
          <h1 className="text-2xl font-bold mb-5">{post.title.rendered}</h1>
            <div className="mb-4">           
              <div
                dangerouslySetInnerHTML={{ __html: post['content']['rendered'] }}
              />  
            </div>
        </div>
        ))}
     </div>
    </div>
  );
}
themes\cairocoders\functions.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//themes\cairocoders\functions.php
<?php
/**
 * Theme functions and definitions
 *
 * @package cairocoders
 */
 
add_action('rest_api_init', 'register_rest_images' );
 
function register_rest_images(){
    register_rest_field( array('post'),
        'fimg_url',
        array(
            'get_callback'    => 'get_rest_featured_image',
            'update_callback' => null,
            'schema'          => null,
        )
    );
}
 
function get_rest_featured_image( $object, $field_name, $request ) {
    if( $object['featured_media'] ){
        $img = wp_get_attachment_image_src( $object['featured_media'], 'app-thumb' );
        return $img[0];
    }
    return false;
}
Run C:\react-j\my-app>npm start
http://localhost:3000/

Related Post