ReactJS + WordPress Search

reactjs wordpress search vancouver island

This post isn't quite done, but check back soon!

To see this in action, try the search in the header.

I want to get this out in the open right off the bat: I’m no ReactJS developer 😳. I put this ReactJS WordPress Search plugin together after seeing someone else do it, and tweaked a bunch of stuff to suit the needs of a project. The search function isn’t a large project, but it was fun and got me more into ReactJS. So if you know your ReactJS and see how I can improve this, please drop a comment below!

I do plan on going back over the plugin as there are some optimizations that I think would help.

I’ve rebuilt it here for this website and have documented the process.

Getting Started: Basic Structure + NPM

I put this search bar into a plugin. The search function is closely tied into my theme (hint: WP Rig), but I wanted it portable anyways.

To kick things off, I created a folder in my /plugins directory. I use terminal, but create the following however you are comfortable:

  • $ cd your/sites/path/wp-content/plugins
  • $ mkdir awc-react-search
  • $ cd awc-react-search
  • $ touch awc-react-search.php

We’ll leave the PHP file alone for now and get started on NPM (Node Package Manager) packages. I’ll assume you at least know what NPM is, and have previously installed a package or three!

Let’s get a package.json file created in plugins/awc-react-search by using $ npm init in terminal. You’ll be met with a few questions. Unless otherwise noted, I pressed ENTER for “yes”,

  • package name: (awc-react-search)
  • version: (1.0.0)
  • description: (whatever you like, or none)
  • entry point: (index.js) (we’ll change this later)
  • test command: I used “test”
  • git repository: I didn’t put one
  • keywords: ditto
  • author: Your name! Or my name!
  • license: (ISC)
  • Is this OK? (yes)

Now let’s install all the packages necessary for this tutorial:

devdependencies:

$ npm i -D @babel/core @babel/preset-env @babel/preset-react webpack webpack-cli babel-loader

dependencies:

$ npm i react react-dom

Your package.json should look similar to mine – the versions may be differ:

Now let’s get webpack going: $ touch webpack.config.js. Open that file up and insert the following:

There is one item in the above file I should point out:

entry: './src/js/public.js',

At the start of this tutorial we created our package.json file and listed the entry point as index.js. I opted for a src folder, so let’s create that and the public.js file.

  • $ mkdir src src/js
  • $ touch src/js/public.js

Now you can run $ npm run watch in the terminal, and assets/js/public.min.js will be automagically 🦄🦄🦄 created!

Next Steps: Make this thing a WP Plugin!

Let’s go back to awc-react-search.php and put in the following code. The code is just enough to make a “plugin” – you can activate it at this point – but it has no functionality. Yet!

The above is pretty much taken from the WordPress Plugin Handbook. You can find the basic header info here.

Now we can start adding more to the main plugin file to get the stuff that we need. We’ll start with basic, minimal security:

// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
	die;
}

Now we’re going to enqueue public.min.js and expose some WP REST API endpoints so that file can access them. To expose the endpoints, we use wp_localize_script. This takes three arguments: the enqueued file’s handle (react-rest-js), the JavaScript object name that will be used in your .js file – in this case wp_react_js, and an array of the data to be passed (key => data).

I used the wp/v2/search endpoint because I wanted to search pages, posts, and custom post types. I think there is a different way to do this but this served my needs.

add_action( 'wp_enqueue_scripts', 'awc_react_search_rest_api_scripts' );
/**
* Enqueueing the script
*/
function awc_react_search_rest_api_scripts() {
    wp_enqueue_script( 'react-rest-js', plugin_dir_url( __FILE__ ) . 'assets/js/public.min.js', array(), '', true );
    wp_localize_script( 'react-rest-js', 'wp_react_js', array(
        //   https://medium.com/@dalenguyen/how-to-get-featured-image-from-wordpress-rest-api-5e023b9896c6
        'rest_search_posts' => rest_url( 'wp/v2/search?search=%s&_embed' ),
        'rest_media_endpoint' => rest_url( 'wp/v2/media/' ),
        )
    );
    wp_script_add_data( 'react-rest-js', 'async', true );
    wp_script_add_data( 'react-rest-js', 'precache', true );
}

You’ll notice I’ve used wp_script_add_data to async and precache our public.min.js file.

I also wanted to include the featured image url in the API response. WordPress doesn’t do this out-of-the-box so Google came to the rescue here. This link helped, but it’s for post/page/CPT endpoints. It works with the endpoint I’ve used, but you have to drill down a bit further. Essentially, I added &_embed to the endpoint in conjunction with the following code from the aforementioned link:

add_action('rest_api_init', 'register_rest_images' );

function register_rest_images(){
    register_rest_field( array('post', 'awc-portfolio'),
        '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' );
        $img = wp_get_attachment_image_src( $object['featured_media'] );
        return $img[0];
    }
    return false;
}

My next step was to put this search box somewhere. I chose to append it to my navigation items, like so:

add_filter('wp_nav_menu_items', 'add_admin_link', 10, 2);

function add_admin_link($items, $args){
    $items .= '<li id="awcSearch" class="awcSearch"></li>';
    return $items;
}

Putting that altogether results in this:

And now for some ReactJS!

We’ll kick things of with the public.js file:

First off, we import React, and ReactDOM. We need to use React, of course, and ReactDOM to render our components.

The third import brings in our searchForm component. This is the component that kicks things off.

To render this component we use ReactDOM.render(searchFormElement, searchField). This function mounts the element variable searchFormElement in the component variable searchField. We defined searchField by grabbing the element #awcSearch from our main PHP file above.

We need to create our searchFormElement component now. From this plugin’s directory we create another directory (components) and the component file: searchForm.js:

  • $ mkdir src/components
  • $ touch src/components/searchForm.js

The basic shell of our component looks like this:

import React from "react";
import SearchResults from "./searchResults";

export default class SearchForm extends React.Component {
    constructor(props) {
    }
    render () {
        return();
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *