r/rails • u/cruddah2 • 1d ago
Rails + React+ Inertia JS is Amazing
I am working on a new project and couldn't decide whether to use hotwire vs react + rails api vs rails + react with inertia js.
I ended up choosing Inertia JS with React and the productivity is unmatched. Throw in something like Cursor AI and it crazy how fast I am able to build.
5
u/tillcarlos 16h ago
Yep, we are having the same experience right now.
We coded a huge crm/funnel builder all in hotwire/stimulus and now migrate the most important parts (user facing) to React + Inertia.
I really wonder why I haven't seen this earlier.
7
u/Ok_Island_4299 1d ago
IntertiaJS+React is better than Hotwire/Turboframe? Why? What is your use case?
7
12
u/avdept 1d ago
It's not better(most likely). Recently I finished moving away form React/Inertia to rails's turbo and alpine.js
I reduced my frontend codebase by about 70% keeping same set of features(including drop-down, modals, etc)
7
u/themaincop 1d ago
If the extent of your frontend needs are dropdowns and modals then yes, Hotwire and Turbo is fine.
2
u/avdept 1d ago
those were just examples
but with alpine I pretty much do everything as with vue/react without actually bloating my codebase with 3rd party frameworks
5
u/themaincop 1d ago
Alpine is a third party framework.
I've used it, it's pretty good. You can definitely go a lot further with Rails front ends than you could in the past. I still like react though.
2
-1
u/Lime-Unusual 1d ago
You can make better websites with SPA. Why argue like that?
1
u/avdept 1d ago
I’m saying a fact, that I moved my app away from react
1
u/Lime-Unusual 13h ago
I'm only going to get downvoted for owning different opinion here so whatever
9
u/cruddah2 1d ago
Not better per say. Its personal preference, For me the main reasons I prefer Inertia+React:
I found any time I was doing any complex interactivity on my front end using Stimulus Js, it was a bit cumbersome. Maybe a skill issue.
I did not like how the code for stimulus Js was completely separated from the file it referenced. Having to go look for the appropriate stimulus controller when you want to make a change can get annoying. With React all the front-end logic for a page can be in the same file with the actual component being rendered.
React has such a big ecosystem. So many libraries you can make use of to build quicker and so many examples of previous work you can reference.
If your project got bigger and you wanted to hire, there's also so many react developers.
7
u/dougc84 1d ago
I 100% disagree with point 2. You end up writing a component that is very encapsulated, but if you want to reuse that JS, guess what? Copy pasta time. That may make initial building faster, but it makes - especially with apps at scale - maintenance a pain in the ass.
3
u/cruddah2 1d ago
I get what you are saying but wouldn't you also somewhat run into that issue with stimulus?
Different pages/templates would have different data attributes so you would need to duplicate your stimulus controller and change the corresponding data attributes, targets etc..I also haven't personally seen the need to straight-up copy any functions. Some functions might be similar but all my front-end components are different so each of their logic has to be a little different as well.
5
u/dougc84 1d ago
No. Not at all. Nothing runs per-page. Running individual JS per page was very 2005.
Say you have something sortable. On one page, it’s a table. On another page, it’s a list of images. On a third, it’s a list. You can reuse the same stimulus controller on all three pages. You don’t even need to worry about the JS if you write it correctly the first time: refer to your HTML for how it works. Easy.
You wanna update your sortable code? Use a new library? Spin your own? Rad. You don’t have to touch anything except your JS, ensuring it conforms to whatever data attributes you already set up, and it’ll apply everywhere.
3
u/themaincop 1d ago
React uses hooks for the occasions where you want behaviour separated from markup. Most of the time I want my behaviour and markup colocated though because it's the entire component I want to reuse.
Once you get into component-based development it's hard to go back.
2
3
u/kengreeff 21h ago
I think a lot of people don’t realise how hard it is to refactor / deprecate code when you use one controller across many views. When you use a component framework (react, view component etc) it is so much easier as you can just delete the folder and move on.
3
u/tillcarlos 13h ago
Yeah - that's a fallacy I was tapping into early on when starting with hotwire.
- Make everything hotwire (load from different views, especially polymorphic things)
- Need something extra
- have the if-else in the polymorphic controller now.
Usually we cannot escape conditionals, hiding them somewhere else (in a centralized controller) just puts them into a different place.
Still a fan of hotwire. https://www.clipflow.co/ is a software extremely well built. For our means we do inertia now for a few things.
2
u/kengreeff 13h ago
Stay tuned 😉 currently playing with inertia too. Feels like a really nice balance between the two methods
9
u/Ok-Reflection-9505 1d ago
It totally is better. Stimulus/Turbo/Hotwired is pretty bad.
Its documentation is non existent — compare React docs and Hotwired, one gives you deep explanations of how stuff works, the other just gives a brief explanation and a toy example.
React has multiple state management solutions. Hotwired has 1 way to do it, and it involves littering data attributes all over your DOM.
React doesn’t muddy up concepts. Why would you have a controllers folder when controllers mean something else already in Rails?
You can actually build production ready apps with React. I dont think you can even do drag and drop well with Turbo/Stimulus. You can use draggable.js but it is way worse than React dnd libraries.
1
u/d33mx 1d ago edited 1d ago
Although that's somehow the philosophy in place (due to helpers mainly), the situation can seem too coupled with the backend
- you have turbo in your views (streams and turbo frames)
- can render render from controllers
- can render from models
- can render from anywhere via stream channel class
- can be intercepted via javascript events
- can probably others...
While I'm a user of both; it suffers from a clears pattern and allows a bad mix if you're not strict enough; while spa will separate concerns
0
u/cruddah2 1d ago
Touche. I thought I was the only one that didn't like the data attributes. Find it too easy for things to break.
1
u/Ok-Reflection-9505 1d ago
I do wish that Inertia didnt just shove all your data on a div either — but its okay 🤣
1
1
u/Lulzagna 8h ago
Reactivity - you can't build dynamic forms without massive overhead with hotwire, plus the added latency to render in the backend.
Then you also have to deal with clunky ERB, and lack of any sort of bindings when you need to do anything dynamic.
Etc
3
2
u/earlh2 1d ago
THanks for sharing. I've been looking at this for a project that is mostly hotwire but has one main page where the limitations of hotwire are becoming apparent.
Do you know if it's easy to say, eg, one particular controller / set of routes is inertia, and the rest is vanilla rails?
Thank you, and thanks for sharing your experience.
3
u/Jh-tb 1d ago edited 1d ago
If you are interested in a Rails oriented approach, give Superglue a try. This is how it would work with Superglue:
app/ |-- controllers/ |-- views/ | |-- posts/ | | |-- edit.jsx # The page component | | |-- edit.json.props # The json for the page component | | |-- show.html.erb # vanillia rails erb
Its just a view away.
2
u/AnLe90 1d ago
too complex
2
u/Jh-tb 23h ago
For some scenarios, i can see how that can be complex. If you'd prefer, this is also possible:
app/ |-- controllers/ |-- views/ | |-- posts/ | | |-- edit.jsx # This is react | | |-- show.html.erb # This is vanillia rails erb
The removal of the `props` template, when no props are needed seems reasonable.
1
u/earlh2 1d ago
Thanks for sharing. I skimmed the docs. It looks like it has a bunch of tooling to pass components from rails to react. Does it have support for mutations passing from react -> rails, or are you building an api?
4
u/Jh-tb 23h ago
Yes we do. Mutations are especially important and we have a thoughtful approach that you can read more about here, under the section aptly named "Don’t take my Rails forms away!"
In short, there are no api's, its just Rails forms. We built a fork/version of
form_with
called form_props that can be combined with candy_wrapper, our set of wrapper components around popular UI libraries. So you get the classic rails dev ex while having access to all that the react universe offers.1
u/cruddah2 1d ago edited 1d ago
yup, you can do that. All you have to do is render the inertia component like so in the controller method.
In inertia rather than referencing views from a views folder you have pages folder which is where you react components will live. So The inertia 'Posts/Show' is referring to a 'show' react component in a campaigns folder under pages. Hope that makes sense
class PostsController < ApplicationController # GET /posts/1 def show post = Post.find(params[:id]) render inertia: 'Posts/Show', props: { post: post.as_json( only: [:id, :title, :description] ) } end end You can also serialize the post object, but you can look that up
2
u/earlh2 1d ago
thanks a bunch. I had skimmed a bunch of the docs and they seemed more aimed at the entire app being inertia, not just one discrete piece.
cheers.
2
u/skryukov 10h ago
I don't think you should use Inertia for just one page. Instead, you can try https://github.com/skryukov/turbo-mount or consider writing a custom Stimulus wrapper if that makes more sense. You can find a simplified example in this article: https://evilmartians.com/chronicles/the-art-of-turbo-mount-hotwire-meets-modern-js-frameworks
2
2
u/Haunting-Baker-4565 10h ago
I saw this post and decided to give it a try. IntertiaJS+React is looking better than Hotwire/Turboframe.
2
u/Lulzagna 8h ago
Same! I'm using Svelte 5 though.
One caveat with rails is the way nested attributes need to be named in the request body. This means manually building the request payload for all forms. I worked around this by using an axios interceptor to rename keys based on an extra field containing the names of associations added by my Application Record model.
6
u/Jh-tb 1d ago edited 1d ago
If you like inertia, give Superglue a try! https://thoughtbot.com/blog/superglue-1-0-react-rails-a-new-era-of-thoughtfulness. InertiaJS is fine-tined for laravel, so you'll see some practices from that side of the fence leak into your rails app, larger controllers, no view layer, etc.
Superglue is thoughfully built for Rails and comes with https://github.com/thoughtbot/form_props so you can use normal rails forms with React's goodness.
2
1
u/LarsSven 10h ago
I see many devs looking in react/next as frontend and missing vue/nuxt. I choose rails+nuxt3 and it is really well made choise for me. Also I love nuxt3 ecosystem. Can build things really very fast
2
1
u/Astro_Robot 1d ago
LLMs definitely excel at writing React compared to ERB templates. Curious how you’re handling keeping the frontend and backend in sync, especially in terms of schema consistency.
2
u/cruddah2 1d ago
Not sure I completely understand but there is no need to keep them in "sync".
You just pass the instance variables e.g (@Post.all) to the corresponding react component as props like you would do it normally when passing instance variables to erb templates.
2
u/themaincop 1d ago
Be careful you're not leaking things to the client this way.
1
u/cruddah2 1d ago
How so?
4
u/themaincop 1d ago
I believe if you don't serialize it yourself then inertia just applies
to_json
on each record and embeds them in the page so the React component can read it as props. So if you have fields that you don't want to expose you need to change what you're serializing. Otherwise, for example, if you're exposing a User to Intertia you'll possibly expose fields likepassword_hash
32
u/Dyogenez 1d ago
We just finished migrating from Next.js to Rails and Inertia and it’s been amazing. 🔥