Up until recently, I had no idea you could create custom events in the browser. Yes, you read that right—you can create and dispatch your own custom events and listen for them in your application.
Why Use Custom Events?
Let me share a use case to explain. I was working on a Chrome extension built with React. The extension consisted of multiple modules, each with its own isolated logic. Some of this logic lived outside React components, in standalone TypeScript files. I needed a way to communicate between these isolated modules and my React app.
While I can't disclose all the details about the extension, imagine you're building a service for car manufacturers, and you're working with Toyota, Ford, and Mercedes. Each manufacturer requires unique handling, so you end up with separate logic files for each. These files aren't React components, so you can't use tools like useState
, React context
, or global state managers like Redux
or MobX
.
Faced with this challenge, I explored various solutions. That's when I discovered custom events.
How Do Custom Events Work?
Custom events allow you to create, dispatch, and listen for events with custom data. Here's the basic syntax:
Adding a Listener
window.addEventListener(type, listener);
-
type
: A case-sensitive string that represents the event's name. -
listener
: A function that runs when the event is dispatched.
You can also pass an optional options object to addEventListener
. Read more about that here
Dispatching an Event
const event = new CustomEvent(eventName, { detail });
window.dispatchEvent(event);
-
eventName
: The name of the custom event (must match the type used inaddEventListener
) -
detail
: An object containing additional parameters to be passed to the listener.
The detail
object makes custom events incredibly powerful because you can send any data to the event listener.
Real-World Example: Using Custom Events in React
Here’s how I implemented custom events in my Chrome extension:
- Set Up the Event Listener
I declared the event listener in a
useEffect
in myApp.tsx
file:
useEffect(() => {
const handleCustomEvent = (event: CustomEvent<{ key: string; value: any }>) => {
console.log(event.detail);
};
window.addEventListener(ADD_CUSTOM_EVENT, handleCustomEvent as EventListener);
return () => {
window.removeEventListener(ADD_CUSTOM_EVENT, handleCustomEvent as EventListener);
};
}, []);
-
ADD_CUSTOM_EVENT
: is the event name (declared as a constant to avoid typos). -
handleCustomEvent
: is the listener function, which logs the event's detail object in this example.
- Dispatch the Event From anywhere in your app, you can dispatch the event like this:
const event = new CustomEvent('ADD_CUSTOM_EVENT', { detail: { key: 'exampleKey', value: 'exampleValue' } });
window.dispatchEvent(event);
Why I Love This Approach
With custom events, I was able to easily trigger and handle events across different parts of my app. It provided a simple and elegant solution for cross-module communication without relying on React-specific tools like context or state management libraries.
I hope this helps someone else as much as it helped me. Custom events are a versatile tool for solving complex communication problems in web applications. Until next time—happy coding!
Top comments (0)