WordPress Plugin API (hooks) are a great way to make your plugins or themes extensible. And that is something that you can use when using PHP. But what if you’re using JavaScript? Maybe you want to make your JavaScript project extensible in a similar way. In this tutorial, we will see how to use those hooks in a React App.

What is @wordpress/hooks?

Before we write any code, let’s understand how we can use those JavaScript hooks. So, @wordpress/hooks is a package, an npm package which you can check out on npmjs.

If your JavaScript app is running under WordPress and Gutenberg is active, you can use it without installing anything by calling it from wp.hooks.

Otherwise, you can include that in your JavaScript app by installing it like this:

npm install @wordpress/hooks --save

Creating your Hook environment

To create your hook environment, you can create a global object that will be accessible throughout your entire app. Or you can use an internal object which you’ll pass to components using the hook system.

import { createHooks } from '@wordpress/hooks';

Now you can use the createHooks function to start your Hook environment like this:

var myGlobalHooks = createHooks();

That’s it! You can now create actions and filters to make your app extensible. If you’re used to the WordPress Plugin API where you can use functions such as add_action, do_action, apply_filters, add_filter, then you will notice a small difference when implementing this hook system.

That difference is the namespace which you also add when adding actions and filters (or removing them). This is done in case you have same function names under different components (or Apps). With using namespaces you can easily distinguish to which component or app it belongs so you don’t accidentaly remove the wrong function.

Actions functions that are available are:

  • addAction( 'hookName', 'namespace', 'functionName', callback, priority )
  • removeAction( 'hookName', 'namespace', 'functionName' )
  • removeAllActions( 'hookName' )
  • doAction( 'hookName', arg1, arg2, ... )
  • doingAction( 'hookName' )
  • didAction( 'hookName' )
  • hasAction( 'hookName' )

Filter functions that are available are:

  • addFilter( 'hookName', 'namespace', 'functionName', callback, priority )
  • removeFilter( 'hookName', 'namespace', 'functionName' )
  • removeAllFilters( 'hookName' )
  • applyFilters( 'hookName', content, arg1, arg2, ... )
  • doingFilter( 'hookName' )
  • didFilter( 'hookName' )
  • hasFilter( 'hookName' )

The string functionName is used so we can remove the registered callback. If it’s not provided, the filter or action will still be applied and called but you might have a hard time removing them later.

You can also view all registered actions and filters by console.log(myGlobalHooks); and you will find actions and filters keys. This is where all your actions and filters will be applied and registered.

Creating the Extensible React App

To jumpstart a simple React App so we have all the build tools set up, I am going to use the “Create React App”. You can check the repository with information on how to use it on Github.

Open your terminal, place yourself in a folder that you use for sites or even on Desktop. Create a folder for the app, for example my-app and type this:

npx create-react-app my-app

You can rename my-app into whatever your folder is called. The render method in App.js now contains all the JSX that will be rendered. With @wordpress/hooks we will make that output (JSX) extensible so we can combine what we want there.

Make sure that you’re inside of the newly created folder. We will now install the @wordpress/hooks package:

npm install @wordpress/hooks --save

Creating our Hook Environment

We will now create a global object that will contain our hook environment.

Let’s all implement some actions and filters. We will do that by changing the render method. It will have a variable output that is an array. We will then use the applyFilters to have a few positions where we can add JSX to our output array.

You can now see that we are using doAction to create a hook where we can do various calls before the output even starts.

Later, we are using three applyFilters calls and then we are rendering our output.

Rendering the Header output

Now, we will actually use the whole JSX that we have been given when we created the app.

In the constructor method, we are adding the filter to the hook header_output, with the namespace myApp and with the callback to our method renderHeader. Since the output is an array, we are receiving an array as a parameter to our method.

We are then applying different filters:

  • header_logo – So we can change the logo
  • should_learn – This filter is returning a boolean. If true, our header will have a link to ReactJS website. By default, it returns true./li>

Once that is passed through our Hook environment, we are building a JSX output and pushing that into our array and returning the array. If you type now inside the terminal (while being inside the app folder) npm start, you should see this in your browser:

This is the same screen you would see if you typed npm start without doing any changes to the App.

Removing the Link through a Filter

Let’s now remove the link Learn React. For that, we will use the filter should_learn that we have applied in our renderHeader method.

In the constructor method we are adding a filter where the method shouldNotLearnReact, that is hooked there, is returning false.

If you now reload the screen, you should see that the Learn React link is missing. That’s happening because we are returning false so the variable shouldLearnReact (defined in renderHeader method) is false.

Removing the Hooked Function

We will now remove the method shouldNotLearnReact from the filter should_learn.

So, what is happening here?

  1. We are hooking a new method youShouldLearnReact on the action before_output,
  2. We are accessing the global hook environment to remove the hooked function using removeFilter.

If you reload the screen, you will see that the link is back on there.

Changing the Logo

Since we have added a filter header_logo where the default value is an SVG logo, we can also change that. You can download any SVG logo or icon you want and place in in the folder src of your app folder. I’ve called it logo2.svg.

We are importing the new logo as logo2. Inside of the constructor method, we are hooking a new method newLogo to the filter header_logo.

Inside of that method, we are checking if the provided logo is the same as logo2. If not, we will return the new logo2 and also we will do an action using doAction. This is a scenario which may happen in any JavaScript app where some value changes and we would like to call some other methods also.

Notifying on Change

Let’s now see how we can notify our user that the logo has been changed.

Again, in our constructor method, we are hooking a method notify to the action logo_changed. Inside of that method we are checking if the provided logoSVG is the same as our newly added logo2. If it is, we are alerting the user.

Displaying data after Header

To display some other data after the header, we will use the filter after_header. That filter is applied on the output variable inside of our render method.

Inside of the method renderAfterHeader, we are pushing a static JSX that will render an h1 tag with words This is After Header. We are pushing that to the content because we are passing and expecting an array.

You should have this screen above now. Don’t forget to scroll a bit if you don’t see it immediately 🙂

Complete Code

Here you can download all the code with the second logo which I’ve used. That part is also commented out so you don’t get alerts all the time. Have fun and play around with it!

This part is available only to the members. If you want to become a member and support my work go to this link and subscribe: Become a Member

Conclusion

The @wordpress/hooks package is something really powerful and if you’re used to using filters and actions within your own plugins/themes or within others you will see the benefit of using this.

By using this package, this really helps others build extensible JavaScript applications.

Have you used a similar way to build extensible JavaScript applications? Let us know about your experience with hooks 🙂

Posted by Igor Benic

Web Developer who mainly uses WordPress for projects. Working on various project through Codeable & Toptal. Author of several ebooks at https://leanpub.com/u/igorbenic.

Leave a reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.