Home » React JS » How to use the WordPress API with React JS

How to use the WordPress API with React JS

By Emily

I started to look at the WordPress Api recently and decided to put together a small React JS web app that would enable me to show my blog data in a custom front end. To start with I’ve focused on getting a a list of posts, and related categories. By following this post, an example of how to use the WordPress rest Api in React, you will have a fully working React JS website showing your WordPress data. I’ve also written a post which is a more general introduction to getting data from an APi using React JS.

Using the WordPress REST API with React

The WordPress API is enabled by default on your WordPress website – if you want to restrict access to your API then this post covers the topic well. To get started type your website’s domain name and add one of the endpoints to it just in a browser window like this:

https://<your-domain-name>/wp-json/wp/v2/posts

…. and then then press return. If your website is configured to serve the Api data then you will see something similar to this:

Check api data is being received

That means you are ready to start coding to use the Api. The documentation here tells you the endpoints required for different data.

Set up a React JS website to use the WordPress Api

Go through the normal procedure of setting up a React JS website by using npx create react app.

Create a file called wordpressApi.jsx and save it in a folder called services. We will keep all of our endpoint methods in this file. Start by defining the base url, which will be your website’s domain name, and then we’ll set constants up which hold each endpoint that we are going to use:

const baseurl = 'https://devpixi.com';
const postsEndpoint = '/wp-json/wp/v2/posts';
const categoriesEndpoint = '/wp-json/wp/v2/categories';

Get posts from WordPress API in React

Next we will write the method that gets all of the posts.

const baseurl = 'https://devpixi.com';
const postsEndpoint = '/wp-json/wp/v2/posts';
const categoriesEndpoint = '/wp-json/wp/v2/categories';

const getPosts = () =>
  new Promise((resolve, reject) => {
    const endpoint = baseurl + postsEndpoint;
    
    console.log("API URL " + endpoint);

    fetch(endpoint)
    .then(response => response.json()
    .then(json => ({
        totalPages: response.headers.get("x-wp-totalpages"),
        totalPosts: response.headers.get("x-wp-total"),
        allHeaders: response.headers,
        json
      })))
    .then(result => {
        resolve(result);
    }).catch((err) => {
        reject(err);
    });
  });

Breaking it down, we:

  1. Define the endpoint by concatenating the baseurl and the postsEndpoint constants.
  2. Use a console.log to show the full endpoint string in the console. Handy to spot errors while developing.
  3. Use fetch to request data from the endpoint
  4. Transform the initial response to json
  5. Build a json object containing 4 properties : totalPages, totalPosts, allHeaders, json.
  6. Finally we resolve the promise and return that object.

Get the header from the fetch response object

The v2/posts endpoint in the WordPress api returns some information in custom response headersx-wp-totalpages which is the total number of published posts, and x-wp-total which is the number of pages.

There are other headers but these two have been exposed by the WordPress backend so that we can reference them. The code includes an extra step in our method to get data from the API, where we build a new response object, and store the 2 headers in a property, and the json body in another property.

totalPages: response.headers.get("x-wp-totalpages"),
totalPosts: response.headers.get("x-wp-total"),
allHeaders: response.headers,
json

Build a React component to show post titles

Now we want to build a component that shows the post titles, so create a folder called components and then add a new file called PostTitles.jsx. Add the following code to that file:

import React, { useEffect, useState } from 'react';
import apiData from '../services/wordpressApi';

export default function PostTitles() {
    const [posts, setPosts] = useState([]);
    
    const getPostsData = async () => {
        try {
          await apiData
            .getPosts()
            .then((data) => {    
              setPosts(data.json);
            });
        } catch (err) {
          console.log(err);
        }
      };

    useEffect(() => {
        getPostsData();
        
   }, [])
  return (
    
    <ul>
      {posts.map((post) =>
          <li key={post.id}>
          {post.title.rendered}
        </li>
      )}
    </ul>
 );
}

Again breaking down this file we reference the apiData object that is exported from the wordpressApi.jsx file we have already created, and that will let us access the method by writing apiData.getPosts(). We then define a state object called posts, and build a method called getPostsData. This method calls apiData.getPosts() and when it resolves stores the json property of the data returned in our posts state.

If an error occurs we make sure it’s caught and in this case simply write the error to the console. We call the getPostsData() method using the useEffect hook, and finally return a list of the post titles. At this stage there is no styling, just putting the data on the screen in it’s simplest form.

Lastly we want to use that component to show the post titles in our main website page. So in App.jsx we will use this code:

import "./App.css";
import PostTitles from "./components/PostTitles";

function App() {
  return (
    <div className="App">
      <header className="App-header">React JS WordPress api example</header>
      <PostTitles />
    </div>
  );
}

export default App;

Looking at this line by line we import the default App.css file which is created by the npx create-react-app process, and then import the PostTitles component that we built earlier, and render the component in the main body by adding <PostTitles /> under the header. If you have put all of that together ok, this is what you should see:

get posts from wordpress rest api using react js
The React JS website so far

Develop the React app further

You’ll notice right away that we have only got 10 posts showing, but I know there are many more published posts than that. By default the posts endpoint will return you the newest 10 posts. So let’s develop the code to adjust how many results we get back. You’ll probably also notice there are some odd characters in amongst those titles – let’s resolve that problem too.

Control how many posts come back from the WordPress Api Posts endpoint

We have to adjust the endpoint first of all, so that the per_page parameter is used to define how many posts we would like returned, rather than the default of 10. We also have to adjust the getPosts method so that we can pass in the number as a variable, and have it appended to the endpoint. You can see both of these changes in this updated code :

const baseurl = 'https://devpixi.com';
const postsEndpoint = '/wp-json/wp/v2/posts?per_page=';
const categoriesEndpoint = '/wp-json/wp/v2/categories';

const getPosts = (count) =>
  new Promise((resolve, reject) => {
    const endpoint = baseurl + postsEndpoint + count;
    
    console.log("API URL " + endpoint);

    fetch(endpoint)
    .then(response => response.json()
    .then(json => ({
        totalPages: response.headers.get("x-wp-totalpages"),
        totalPosts: response.headers.get("x-wp-total"),
        allHeaders: response.headers,
        json
      })))
    .then((result) => {
        resolve(result);
    }).catch((err) => {
        reject(err);
    });
  });

We also have to update our PostTitles component, so that we can pass in a number as a parameter, and so that where we call the apiData.getPosts method, we now pass that number on, as follows:

export default function PostTitles({numberOfPosts}) {
    const [posts, setPosts] = useState([]);
    
    const getPostsData = async () => {
        try {
          await apiData
            .getPosts(numberOfPosts)
            .then((data) => {    
              setPosts(data.json);
            });
        } catch (err) {
          console.log(err);
        }
      };


    useEffect(() => {
        getPostsData();
        
   })
  
...
...


And finally where we use the component in the App.jsx file we have to add the number of posts as a parameter:

...

<PostTitles numberOfPosts="22" />
  
...

Fix the strange characters by parsing them

We will add a package called html-react-parser which will enable us to parse the text and to decode any special characters. Let’s install html-react-parser:

npm install html-react-parser --save

And now we’ll import the parse function from the html-react-parser package, and modify the line where we render the actual title by passing the title into the parse function.

import parse from "html-react-parser";


...


{posts.map((post) =>
  <li key={post.id}>
    {parse(post.title.rendered)}
  </li>
)}


...

Add some styling to the website

Now we are going to add some styling to the website by using Bootstrap. If you haven’t used it before then you may find my previous post explaining how to use Bootstrap with React Forms useful. Stat by installing Bootstrap :

npm install react-bootstrap bootstrap

Now we’ll import the bootstrap css and Row and Card components by adding this at the top of our PostTitles.jsx file:

import "bootstrap/dist/css/bootstrap.min.css";
import Row from 'react-bootstrap/Row'
import Card from 'react-bootstrap/Card'

...

I’ve grabbed some example code from the React Bootstrap documentation and modified a few properties so that we can now display our list of posts in a grid.

import React, { useEffect, useState } from 'react';
import apiData from '../services/wordpressApi';
import parse from "html-react-parser";

import "bootstrap/dist/css/bootstrap.min.css";
import Row from 'react-bootstrap/Row'
import Card from 'react-bootstrap/Card'


export default function PostTitles({numberOfPosts}) {
    const [posts, setPosts] = useState([]);
    
    const getPostsData = async () => {
        try {
          await apiData
            .getPosts(numberOfPosts)
            .then((data) => {    
              setPosts(data.json);
            });
        } catch (err) {
          console.log(err);
        }
      };

    useEffect(() => {
        getPostsData();
        
   })
  return (
    <Row xs={1} md={2} className="g-4">
      {posts.map((post) =>
        <Card style={{ width: '18rem', marginRight:'10px' }} key={post.id}>
        <Card.Body>
          <Card.Title>{parse(post.title.rendered)}</Card.Title>
          <Card.Subtitle className="mb-2 text-muted">{post.categories[0]}</Card.Subtitle>
          <Card.Text>
            {parse(post.excerpt.rendered)}
          </Card.Text>
          <Card.Link href={post.link}>{post.link}</Card.Link>
        </Card.Body>
      </Card>
      )}
    </Row>
 );
}

If you check the website it will now look like this:

Wordpress website with data

Instead of just showing the post titles in a <ul> list, we are now using a Bootstrap card component in a grid, and we have accessed a few more properties of each post object too, now showing the title, the category id, the excerpt, and the post link.

Now I want to be able to show the cards in a grid, control how many are shown per row, and modify the link text. So we add a few more details and the code becomes this:

import React, { useEffect, useState } from 'react';
import apiData from '../services/wordpressApi';
import parse from "html-react-parser";

import "bootstrap/dist/css/bootstrap.min.css";
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import Container from 'react-bootstrap/Container';
import Card from 'react-bootstrap/Card';

export default function PostTitles({numberOfPosts}) {
    const [posts, setPosts] = useState([]);
    const columnsPerRow = 4;

    const getPostsData = async () => {
        try {
          await apiData
            .getPosts(numberOfPosts)
            .then((data) => {    
              setPosts(data.json);
            });
        } catch (err) {
          console.log(err);
        }
      };

      const getColumnsForRow =()=>{
        let items = posts.map((post, index) => {
          return ( 
            <Col>
            <Card key={post.id}>
            <Card.Body>
              <Card.Title>{parse(post.title.rendered)}</Card.Title>
              <Card.Subtitle className="mb-2 text-muted">{post.categories[0]}</Card.Subtitle>
              <Card.Text>
                {parse(post.excerpt.rendered)}
              </Card.Text>
              <Card.Link href={post.link}>View post</Card.Link>                 
            </Card.Body>
          </Card>
        </Col>
          );
   
      });
      return items;
    };

    useEffect(() => {
        getPostsData();        
   })

  return (
    <Container>
        <Row xs={1} md={columnsPerRow} className="g-4 mt-1">
           {getColumnsForRow()}
        </Row>
    </Container>  
   );
  
};
 

You’ll see that the <Row> element now contains a reference to a method called GetColumnsForRow(). This method loops through the list of posts and creates a set of columns for each row.

All being well, this is what it now looks like:

showing the data in a grid

Summary

This post has shown you how to use Fetch to Get data from the WordPress API in a React app (read this if you want to know how to get data from an API using Axios).You could use this WordPress rest api example to further develop and code a full WordPress blog using React and the WordPress API. I’m interested in exploring further building a full website with headless WordPress, possibly using Next.js to make it super fast. Let me know if you have any experience of this, I’d love to hear how it worked out. If you need Hosting for your React app or WordPress website, check out my review of Cloudways hosting.