Created
June 15, 2023 23:37
-
-
Save drnic/b1987712713906b99f5e1357d6063909 to your computer and use it in GitHub Desktop.
In Rails apps using StimulusJS, load React components found at app/javascript/react/*/index.tsx, and make them available via Ruby helper react(name)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
const Hello = ({ name }: { name: string }) => <span>Hello {name}</span>; | |
Hello.defaultProps = { name: "World" } | |
export default Hello; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="py-32 max-w-2xl m-auto text-center flex flex-col items-center justify-center"> | |
<h1 class="mb-2">Welcome to React on Rails</h1> | |
<div id="hellos" class="my-4 bg-white p-4 border border-gray-200 rounded"> | |
<%= react("Hello") %> | |
<%= react("Hello", props: {name: "Dr Nic"}) %> | |
</div> | |
<%= button_to "Add", send_react_component_path, class: "btn btn-primary" %> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Controller } from "@hotwired/stimulus" | |
import React from "react" | |
import ReactDOM from "react-dom/client" | |
import modulePaths from "../react/**/index.tsx" | |
const modules = {} | |
// Snazzy code written by Marco Roth on discord | |
const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1) | |
const camelize = string => string.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase()) | |
modulePaths.forEach((file) => { | |
const name = file.filename.split("/").reverse()[1] | |
const identifier = capitalize(camelize(name)) | |
if (!modules.hasOwnProperty(identifier)) { | |
modules[identifier] = file.module.default | |
} | |
}) | |
export default class extends Controller { | |
static values = { | |
component: String, | |
props: Object | |
} | |
connect() { | |
const module = modules[this.componentValue] | |
if (module) { | |
this.root = ReactDOM.createRoot(this.element) | |
this.root.render( | |
React.createElement(module, this.propsValue) | |
) | |
} else { | |
console.error(`Could not find module ${this.componentValue}`) | |
} | |
} | |
disconnect() { | |
this.root.unmount() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ReactHelper | |
def react(component_name, props: {}, **args) | |
content_tag(:div, "", data: { | |
controller: "react", | |
react_component_value: component_name, | |
react_props_value: props | |
}, **args) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= turbo_stream.append "hellos", | |
react("Hello", props: {name: Faker::Name.first_name}) %> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment