Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

Using custom events in React

5 min read 1426

Events are one of the integral features of the web as we know it. Without events, the web would most be terribly bland.

Events are actions that happen on a web page to HTML elements. Any time something happens on a web page, you can be sure it’s most likely an event, from when the page loads initially, to the user clicking a button, to closing or resizing a window. They’re all examples of different events that happen in the browser.

As a scripting language for the web, JavaScript lets us execute code in reaction to the occurrence of an event fired by HTML elements.

For JavaScript frameworks, events can also be used to pass data easily across an application. For example, React only supports unidirectional data flow, which means data can only pass from top level components to lower level components. But with events, you can listen for and react to certain events on any component level.

This article will cover how we can create and use custom events in React.


What are custom events?

The browser has a set number of default events available to various HTML elements. But then, in some cases, the need to create a custom event arises. For example, if you’d like to communicate to another component when a dialog component has been closed, the best way to achieve that would be through a custom event, as there is no such thing as an “onDialogClose” event in the browser.

Custom events are also known as “synthetic” events.

We can create custom events using the Event constructor. We can now finally create our non-existent “onDialogClose” event as such:

//First, we initialize our event
const event = new Event('onDialogClose');

// Next, we dispatch the event.

If we wanted to add a bit more data to our custom event, we could do so through the CustomEvent interface using the detail property:

//First, we initialize our event
const event = new CustomEvent('onDialogClose', {detail: "Main Dialog"});

// Next, we dispatch the event.

Check out this well-written article to learn more about custom events in JavaScript and how to implement them in your vanilla JavaScript projects.

Custom events in React

For this article, we’ll build a demo to illustrate how to make use of custom events in our React applications.

For the demo, our use case would be trying to display and hide a list of African countries, which will be contained is a CountryList.js component and declared in our application’s parent component App.js from another child component, ListControl.js.

For fetching the list of African countries, we’ll use the REST countries API.

App component diagram

Let’s dive in!

Project setup

First of all, we’ll create a new React project using Create React App.

Next, we’ll create a components folder in the src folder and create our components CountryList.js and ListControl.js inside of it.

The CountryList.js component will render the list of all countries in Africa from our API endpoint, and the ListControl.js component will contain buttons that will either display or hide the list, depending on its current state.

Also, in the root of our src folder, we’ll create an events.js file to abstract the code for emitting and listening for events, so our code is a bit cleaner and reusable.

Building a custom event in React

Once you’ve completed the instructions above, go ahead and copy and paste into your code editor the contents of the code blocks below. Don’t worry, we’ll go over everything in detail.

First, the event.js file:


function subscribe(eventName, listener) {
  document.addEventListener(eventName, listener);

function unsubscribe(eventName, listener) {
  document.removeEventListener(eventName, listener);

function publish(eventName, data) {
  const event = new CustomEvent(eventName, { detail: data });

export { publish, subscribe, unsubscribe};

In the event.js file, as stated earlier, we’re only abstracting the logic for creating a custom event, dispatching the event, adding event listeners and removing event listeners for use in other components of our application.

You can rename the function names here to whatever you like, I just thought this naming pattern worked well with the publisher-subscriber pattern 😉

Next up is the CountryList.js component:


const CountryList = (props) => {
    return (
            <h2>List of countries in Africa</h2>
            { => {
                return (
                    <li key={el.tld}>
                          <img src={el.flags.svg} alt={}
                            style={{ width: "20px", marginRight: "5px" }} />
                        <span style={{fontSize: "20px"}}>{} </span>
export default CountryList;

This component accepts a prop from its parent component which, according to our diagram above, is App.js. We’ll get to that in a bit.

It displays the data such as country name and flag from the API. I’ve gone ahead to add a bit of inline styling to the list item so it looks better.

More great articles from LogRocket:

Next is our ListControl.js component:

import { publish } from "../events"
const ListControl = (props) => {
  const showList = () => {
  const hideList = () => {
  return (
        props.listState ? <button onClick={hideList}>Hide List</button> :
        <button onClick={showList}>Show List</button>
export default ListControl;

This component contains the button control logic for showing or hiding the list of countries.
It’s also where events for both actions will be dispatched.

We import the publish function from our events file and use it to create the custom events and dispatch them.

In addition, this component receives a prop from the App.js component that tells it when the list is rendered or not, and depending on the state of the list, renders one of two buttons: “Show list” and “Hide list”.

Last but not least, we have the parent component App.js:

import './App.css';
import { useState, useEffect } from "react";
import ListControl from './components/ListControl';
import CountryList from './components/CountryList';
import { subscribe, unsubscribe } from "./events";

const App = () => {
  const [isOpen, setIsOpen] = useState(false);
  const [countryList, setList] = useState([]);

  useEffect(() => {
    subscribe("showList", () => setIsOpen(true));
    subscribe("hideList", () => setIsOpen(false));

    async function fetchData() {
      const apiUrl = '';
      const response = await fetch(apiUrl)
      let data = await response.json()

    return () => {
  }, []);

  return (
    <div className="App">
      <h1>Using Custom Events In React</h1>
      <ListControl listState={isOpen}></ListControl>
        isOpen ? <CountryList listData={countryList}></CountryList> :
            Click on the Button above to render the list of African Countries
export default App;

The parent component first imports all the necessary components and React Hooks for it to function.

Next, we declare our app’s default state with the useState hook.

Remember the ListControl component which creates and dispatches (or “publishes”) the various custom events? Well, this is the component where we listen for and “subscribe” to those events.

Also, when our app is first loaded, the various event listeners get activated and then the fetchData function is triggered inside of the useEffect hook, which makes a HTTP request to the API and stores the returned data in our app’s state.

Basically, when the showLis``t event is published, the value of isOpen is changed to true, which in turn displays the list. And when the hideList event is published, the value of isOpen is changed to false and it hides the list component and returns a message instead.

Inside of the useEffect hook, we have a cleanup return function, which removes all event listeners when the component unmounts. This prevents multiple unused event listeners from being created, which would lead to a memory leak in our application.

And Voila! here’s the output of our work so far.

custom event react demo


In this article we learned about events and custom events in vanilla JavaScript. We also went further to discuss how we could implement the same pattern inside of a React application.

All the code for this tutorial is hosted on GitHub here. Feel free to fork it and play around with the code, and if you loved this tutorial, please do give it a star.

Also, feel free to leave your thoughts in the comment section below.

Thank you for reading!

Cut through the noise of traditional React error reporting with LogRocket

LogRocket is a React analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your React applications.

LogRocket automatically aggregates client side errors, React error boundaries, Redux state, slow component load times, JS exceptions, frontend performance metrics, and user interactions. Then LogRocket uses machine learning to notify you of the most impactful problems affecting the most users and provides the context you need to fix it.

Focus on the React bugs that matter — .

Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

2 Replies to “Using custom events in React”

  1. Custom events are also known as “synthetic” events.

    You need to check this statement. Synthetic events are react wrappers over native HTML events. Custom events are what you described in your article.

  2. For unsubscribe to work you need to pass the initial function. So unsubscribe(“hideList”); need the pointer to the function.

    let f = setIsOpen(false);
    subscribe(“hideList”, f);

    and later:
    return () => {

Leave a Reply