Connecting React.js and StimulusJS with JavaScript Events

Connor James
Robert Beekman

Connor James and Robert Beekman on

Connecting React.js and StimulusJS with JavaScript Events

We recently added a "Getting started" page to AppSignal, which shows new users a page filled with recommended steps to help them get the most out of their AppSignal experience.

Some users enjoy having a helping hand when getting started with AppSignal, while others prefer exploring our product solo or already have experience with AppSignal.

To give all our users the option of a guided or solo experience, we designed a toggle that hides and shows the "Getting started" page.

The Challenge

Giving users the ability to toggle the "Getting started" page from their personal settings menu was a little more challenging than you might expect. That's because the "Getting started" page is built in React.js, and the personal settings menu is a Rails-generated template rendered outside of the React app.

We had to find a way of syncing the toggle state on the Rails-generated and React menus, ideally without polling the server for the current state.

The Solution

For our non-React interactions, AppSignal uses StimulusJS in the "Rails way", adding interactive sprinkles of JavaScript joy throughout your application.

We chose StimulusJS vanilla JS as it has a standardized structure that is well documented and can be easily adopted by any Rails developer with some JavaScript experience.

To keep React.js and StimulusJS in sync, we created custom events dispatched on the document body. We configured our React and StimulusJS setups to connect and listen for our hide_getting_started events.

In StimulusJS

When the StimulusJS controller connects, we listen to events on the document. To keep our JavaScript neat and tidy, we remove the event listener on disconnect:

export default class extends Controller { connect() { this.boundToggleSwitchState = this.toggleSwitchState.bind(this); document.addEventListener( "hide_getting_started", this.boundToggleSwitchState ); } disconnect() { document.addEventListener( "hide_getting_started", this.boundToggleSwitchState ); } toggleSwitchState(event) { // Update own state if it differs if (this.currentValue != event.detail) { this.currentValue = event.detail; } const classList = this.toggleTarget.classList; if (this.currentValue) { classList.remove("c-toggle--on").add("c-toggle--off"); } else { classList.add("c-toggle--on").remove("c-toggle--off"); } } // [...] }

In React.js

We do the same thing in React.js as we do in StimulusJS. Our React.js code listens for events on the document and removes the event listener on disconnect:

export const Navigation = () => { useEffect(() => { const toggleHideGettingStarted = (event) => { // handle state here }; document.addEventListener("hide_getting_started", toggleHideGettingStarted); return () => { document.removeEventListener( "hide_getting_started", toggleHideGettingStarted ); }; }); // [...] };

Toggle On, Toggle Off

With this setup, we can emit custom events from both our independent React.js and StimulusJS implementations, allowing them to interact with one another and always reflect the correct state:

const event = new CustomEvent("hide_getting_started", { detail: newValue }); document.dispatchEvent(event);

The great thing about JavaScript is that even in a scenario like ours, where you use different frameworks, you can utilize events to handle changes outside your React.js or StimulusJS components and controllers.

This simple and straightforward solution allows you to manage the state between different JavaScript implementations without modifying the DOM or creating a more complex solution that sends requests back and forth between the back-end and front-end.

Monitor your Front-end JavaScript with AppSignal

Would you like to monitor your application's JavaScript front-end with a tool made by developers, for developers? Developers say they enjoy using our monitoring because we have:

  • An intuitive interface that is easy to navigate.
  • Simple and predictable pricing.
  • Developer-to-developer support.

If you're new to AppSignal, remember to ask us for some free stroopwafels! They taste almost as good as it feels to have all of your application's metrics at your fingertips 😉🍪

Connor James

Connor James

Official technical writer at AppSignal. Podcast addict who loves cannoli so much that he's considering changing his name to Connoli. He thinks there's a `u` in color. You might find him on the mic, on the stage, or lying on the sofa when he's off Documentation Duty.

All articles by Connor James
Robert Beekman

Robert Beekman

As a co-founder, Robert wrote our very first commit. He's also our support role-model and knows all about the tiny details in code. Travels and photographs (at the same time).

All articles by Robert Beekman

Become our next author!

Find out more

AppSignal monitors your apps

AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!

Discover AppSignal
AppSignal monitors your apps