Home >Web Front-end >JS Tutorial >React Component Mounting with Rails: Simplifying Dynamic Interfaces
Modern applications often require dynamic interfaces that can handle API calls, dynamic forms, and routing, and React is an excellent choice. However, React's single-page application (SPA) approach doesn't quite mesh with Ruby on Rails, a full-stack framework that renders content server-side. While it's possible to use React with Rails by setting up an API backend or using Webpack integration, this adds considerable complexity and development time.
Challenge
In projects like Raive and Dunu506, we need dynamic features like complex wizards that require real-time interaction. Rails’ traditional server-side rendering is cumbersome for these use cases, and the dynamic nature of React is a perfect fit.
But how do you use React without fully adopting SPA? The solution is simple: we can mount React components in Rails views without giving up Rails’s server-side rendering approach.
Solution
React components can be attached to specific elements in server-side rendered views. Here’s how we start:
Basic mounting: In app/javascript/packs/application.js, we mount a simple React component:
<code class="language-javascript">import React from 'react' import ReactDOM from 'react-dom' import Hello from './Hello' document.addEventListener('DOMContentLoaded', () => { const div = document.querySelector('#hello') if (div) { const props = JSON.parse(div.getAttribute('data-props')) ReactDOM.render(<Hello />, div) } })</code>
Reusability: We then created a reusable function to dynamically mount the component:
<code class="language-javascript">import MyReactComponent from './MyReactComponent' function mountComponent(id, Component) { document.addEventListener('DOMContentLoaded', () => { const div = document.querySelector(id) if (div) { const props = JSON.parse(div.getAttribute('data-props')) ReactDOM.render(<Component {...props} />, div) } }) } mountComponent('#my-react-component', MyReactComponent)</code>
Handling multiple components: For situations where the same component needs to be reused in multiple places, we generalized the method:
<code class="language-javascript">function mountComponent(selector, Component) { document.addEventListener('DOMContentLoaded', () => { const elements = document.querySelectorAll(selector) elements.forEach(element => { const props = JSON.parse(element.getAttribute('data-props')) ReactDOM.render(<Component {...props} />, element) }) }) }</code>
Avoid conflicts: To avoid conflicts with other CSS or JS classes, we decided to use a custom data-component attribute instead of using id or class:
<code class="language-javascript">function mountComponents(components) { document.addEventListener('DOMContentLoaded', () => { const roots = document.querySelectorAll('[data-component]') Array.from(roots).forEach((root) => { const props = JSON.parse(root.dataset.props) const Component = components[root.dataset.component] ReactDOM.render(<Component {...props} />, root) }) }) } mountComponents({ MyReactComponent })</code>
Results
This solution provides a clean, reusable way to mount React components in Rails views. It allows us to take advantage of the dynamic capabilities of React while maintaining the simplicity of Rails server-side rendering. We packaged this approach into a library that can be used in any project, saving development time and streamlining our workflow.
Conclusion
By using the data-component attribute and creating a simple function to dynamically mount a React component, we successfully combined the power of React with the traditional server-side rendering approach of Rails. This approach is flexible, reusable, and concise, making it a good choice for teams that need dynamic interfaces in Rails applications.
Feel free to check out our GitHub repository for more details and to get involved in the project!
The above is the detailed content of React Component Mounting with Rails: Simplifying Dynamic Interfaces. For more information, please follow other related articles on the PHP Chinese website!