StimulusJS is awesome. No more writing $(document).ready(). Instead, StimulusJS uses lifecycle callbacks similar to React Components or iOS UIViewControllers.
So how do you use StimulusJS to mount a React App? After several years of experimenting, I found a way that is simple and also works with Turbo (and Turbolinks).
Let’s dive in using a simple Posts example.
posts_controller.js
import { Controller } from "stimulus";
import React from "react";
import ReactDOM from "react-dom";
import PostsApp from "../bundles/posts/App";
export default class extends Controller {
get props() {
return JSON.parse(this.data.get("props"));
}
connect() {
ReactDOM.render(
<PostsApp props={this.props}/>,
this.element
);
}
disconnect() {
ReactDOM.unmountComponentAtNode(this.element);
}
}
connect()
When our controller is mounted, connect is called. At this time we mount our react component to the binding element which is this case is a div.
disconnect()
Since we are using Turbo, we want to unmount our react app.
props()
Used to pass props into our react app.
posts.html
<div data-controller="posts" data-posts-props="{ 'key1': 'value1', ... }" />
data-controller
References our posts_controller.js
data-posts-props
Props we want to pass to our react app.
More Useful Controllers
I use StimulusJS for all my javascript components. For a list of some of my most used controllers, head over to my Ruby on Rails starter template on Github: https://github.com/davedkg/davedkg-rails-template