Close up of the center of a sunflower

Using The useEffect React Hook In WordPress

React, the JavaScript framework we use in the WordPress editor uses hooks. The new React documentation has a lot of examples in the useEffect reference. But how does that work in WordPress?

React for WordPress is still React, but everything is still a little WordPress. This post explains how to use useEffect in WordPress.

What Is An Effect?

Code often has side effects. For example, when you click on a button, one or more functions bound to the click event for that element may be called. That’s an effect. Effects are changes that occurs as a result of some action or event.

In React, an effect is a function that is called after a component renders, and can be used to perform side effects, such as fetching data from an API or manipulating the DOM.

We use the useEffect hook for that. Keep in mind that useEffect is an “escape hatch,” it breaks out of the React model.

Removing WordPress Admin Notices In A React-Powered Settings Page

It is common to use React to create a settings page in wp-admin. One downside is that there is likely a bunch of admin notices spamming up your screen.

Here is how to use the useEffect hook to remove all the WordPress admin notices when your comonents loads.

const RemoveAdmin = () => {
    //Remove some of the WordPress elements in admin
    useEffect(() => {
      //Bail early if we do not have WordPress elements to remove.
      if (null == document.getElementById("adminmenumain")) {
        return;
      }
      document.getElementById("adminmenumain").remove();
      document.getElementById("wpfooter").remove();
      document.getElementById("wpcontent").style.marginLeft = "0px";
    }, []);
  }

Fetching From An Api In A React Component

In this example, we create a state variable posts using the useState hook, and initialize it to an empty array. We then use the useEffect hook to fetch the posts from the WordPress site when the component mounts. The second argument to useEffect is an empty array, which means that the effect will only run once, when the component mounts.

import React, { useState, useEffect } from "react";

function App() {
  //State for posts
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    const fetchPosts = async () => {
      const response = await fetch("https://roysivan.com/wp-json/wp-json/wp/v2/posts");
      const data = await response.json();
      setPosts(data);
    };
    fetchPosts();
  }, []);

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

export default App;

The Dependencies Argument of useEffect

In that example, we passed an empty array to the dependencies argument so the hook would only run once. Dependencies in useEffect allow you to control when the effect runs. By default, useEffect will run after every render of the component, but you can specify a list of dependencies that will cause the effect to run only when one or more of those dependencies change.

The last example only runs once, but what if we want to run it again, for a second page? In the next example, I added two new state variables: page and totalPages. 

I also added a select control to choose the page. That controls the value of page via the handlePageChange function. You might be tempted to fetch in the handlePageChange function, but that’s not its purpose. Also, that would be a big refactor.

Instead, in the useEffect hook, I mde page a dependency. That way as a side effect of the variable page changing value, the posts are fetched for that page.

import React, { useState, useEffect } from "react";

function App() {
  const [posts, setPosts] = useState([]);
  const [page, setPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);

  useEffect(() => {
    const fetchPosts = async () => {
      const response = await fetch(`https://example.com/wp-json/wp/v2/posts?page=${page}`);
      const data = await response.json();
      setPosts(data);
      setTotalPages(response.headers.get("X-WP-TotalPages"));
    };
    fetchPosts();
  }, [page]);

  const handlePageChange = (event) => {
    setPage(event.target.value);
  };

  return (
    <div>
      <h1>Posts:</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title.rendered}</li>
        ))}
      </ul>
      <div>
        <label htmlFor="page">Page:</label>
        <select id="page" value={page} onChange={handlePageChange}>
          {Array.from({ length: totalPages }, (_, i) => (
            <option key={i + 1} value={i + 1}>
              {i + 1}
            </option>
          ))}
        </select>
      </div>
    </div>
  );
}

export default App;

Use Special Effects!

That’s a short intro to useEffect. Effects are very powerful, but also can get out of hand fast. Make sure to read why you might not need an effect. Also, watch the console for infinite loops.

If you’re interested in learning more about WordPress and React development, be sure to join my mailing list. You’ll receive all my posts about building with WordPress and React.

Featured image by me, via WordPress photos.

New eBook

Refactoring WordPress Plugins

The PHP Parts

 For experienced WordPress developers who are looking to improve the PHP in their plugins, use new modern best practices and adopt test-driven development.