I have written a few articles about how much I like Server Side Rendering (SSR) and using Stimulusjs.
But sometimes you need the power of React to help you. How can we include React when we need it without weighing down our website when we don't?
It's actually not too tough with built in code splitting in Webpack or parceljs. So let's go throught the basics.
Our Stimulus Controller
import {Controller} from "stimulus";
export default class extends Controller {
//Load the React code when we initialize
initialize(){
this.reactComponentPromise = import("./reactComponent");
}
connect(){
this.reactComponent = await this.reactComponentPromise;
const reactRoot = this.targets.find("reactRoot");
const props = {
onChange: this.onChange.bind(this)
}
this.reactComponent.render(reactRoot, props);
}
onChange(){
//Some sort of thing to do with the changes.
//Hit the API?
//IDK you decide
}
disconnect(){
const reactRoot = this.targets.find("reactRoot");
this.reactComponent.destroy(reactRoot);
}
}
It's pretty simple. But now we can load a react component and enjoy code splitting to not weigh down our app!
What does this look like on the React Side?
The React Code
import ReactDOM from "react-dom";
import Something from "./Something";
function render(node, props){
ReactDOM.render(node, <Something {...props} />
}
function destroy(node){
ReactDOM.unmountComponentAtNode(node);
}
export {
render,
destroy
}
This is really all there is to it.
Keep in mind as well that React is pretty smart. You can call render
with new props from your Stimulus controller and it won't break anything.
The HTML
Finally the html to put it together. It's nothing major
<div data-controller="react-controller">
<div data-target="react-controller.reactRoot"></div>
</div>
Conclusion
There is a great case for mixing technologies in your applications using the right too where you need it.
You can easily mix React where you need to do some heavy lifting and still keep your app mostly SSR for the rest of your pages with Stimulus.
If you have any questions let me know!
Top comments (3)
instead of this ReactDOM.render(node, Something);
should be this ReactDOM.render(Something,node); - first comes element you want to render, and second argument is container.
Awesome writeup. Can you explain the purpose of 'await connect()'?
Its just a typo. Thanks for pointing it out