Fork me on GitHub
#helix
<
2022-09-02
>
Ferdinand Beyer16:09:56

@lilactownThank you. I just finished migrating an app that uses Material UI from re-frame/reagent to Helix. Frankly, migrating was no fun, but the result is so much faster! The UI finally feels snappy and “native”! I guess especially when integrating with JS libs, all that Hiccup parsing and data conversion comes with a price.

2
🆒 1
🙌 1
rafaeldelboni18:09:31

Out of curiosity, how you handling the state in a big app like that?

rafaeldelboni18:09:09

BTW I would love to read more about this migration, if you like to write would be a nice blog post

Ferdinand Beyer07:09:27

Good to know! Sure, I might write something up 🙂 For state, I created a port of re-frame that does not use reagent. I call this refx, and after some more testing I am planning to release it. https://github.com/ferdinand-beyer/refx

lilactown17:09:33

minor feedback @U922FGW59on refx: I found that providing a deps.cljs with Helix was a hassle. when people want to install the latest version of things (e.g. React 18, an new version of the uSES shim), shadow-cljs shows warnings that the versions conflict. I got a lot of questions about it. It was easier to just tell people what they needed to install in the README

👍 1
lilactown17:09:40

otherwise looks cool!

Ferdinand Beyer06:09:25

Thanks! Sounds like the issue with deps.cljs is more that the version specs are too narrow and/or a shadow-cljs issue?

Omar10:09:09

Hey @U922FGW59, was the motivation for the port purely because of slow UX? I personally haven't had an issue with reagent, especially when I eliminate unnecessary re-renders. I just discovered that this exists so wondering if you did any precursory benchmarks between the two before you decided to take on that task.

Ferdinand Beyer10:09:47

I have not done any benchmarks yet, but I am planning to. My motivation was based on multiple factors. One was that my UI did feel slow, especially on phones. I am using MUI for the UI so I needed a lot of “interop”, some of which is just obviously wasteful: Embedding a react component in hiccup that expects a react node as a property leads to: Hiccup => React => Hiccup => React. This might be different for UIs that are built with ClojureScript only. A second motivation was that I learned about UIx and later Helix, who both claim to be targeting “modern” React and therefore being faster and more “future proof” than Reagent. I was curious to try these and to see how they feel. I had in the past felt some pain on using hooks with Reagent, which requires extra ceremony, and used function components with hooks in TypeScript projects. Third, I realised that my main blocker for switching was re-frame, which is based on reagent, and I was eager to use this opportunity to dive deeper into re-frame’s implementation and see how easy it would be to port it to a different library. I found this surprisingly easy as re-frame itself does not actually care how your views are implemented, and it only uses reagent for its subscription system. All the other parts: events, interceptors, event-loop, are 100% independent. Finally, this is a hobby project of mine, that I also use to test out different tech choices. I did not need to convince anyone to invest into the port. I also noticed that my attitude towards React with ClojureScript changed. First I aimed to write the UI as “clojuresque” as possible: Components were mostly pure functions using kebab-case keyword props, and therefore did not even need any external dependency. I have to say, this feels right and great. But. As soon as you interop with JavaScript libraries like MUI, the abstraction leaks. You find yourself in more and more places where you need to mix nice kebab-case Clojure maps and JavaScript camelCase objects or maps. It is surprisingly hard (for me) to keep track of the context a component is used in and apply the correct transformations all the time. Debugging these mistakes is not always easy. I ended up writing more and more utility functions to convert back and forth and keep my code “clean”, at the price of complexity and performance. With Helix, all my reagent.core/as-element calls were gone. I do need more pure JavaScript objects, and I changed all kebab-case properties for MUI components to camelCase, but all in all my code actually got a lot simpler. If I was to start over, I would probably go a step further and try to keep my UI code “JavaScript-esque”: Using PascalCase component names and camelCase properties for my custom components, as this makes the code more consistent when using MUI a lot. Compare:

($ RegistrationForm {:onSubmit #(,,,)}
   ($ Button {:onClick #(,,,)}))
instead of:
($ registration-frm {:on-submit #(,,,)} ;; ClojureScript component
   ($ Button {:onClick #(,,,)}))        ;; JavaScript (MUI) component

Omar10:09:12

Makes complete sense in the context of what you're doing! I have a hobby side project that I've barely started and most likely give Helix a try. Would love to see the result of the benchmarks when you do that.

👍 1
Ferdinand Beyer10:09:47

To be honest, I am a bit hesitant to do a lot of benchmarks. There is no such thing as “fast” or “slow”, there is only “fast enough”. Hiccup is great, and if you get an app running that runs smoothly with re-frame, awesome! There are a lot of apps out there that work just fine. Then again, with refx and uix, you might get very close to what re-frame and reagent provide, and Helix can be used to peal away another translation layer, so I hope in the future basing your project on refx should give you more flexibility than re-frame.

xlfe10:09:29

Did you checkout Keechma-next at all?

xlfe10:09:37

All good - I've used it for a few projects now (+helix, mui and react 18) - so was curious about comparisons with your approach :)

👍 1
Ferdinand Beyer11:09:37

@UMMMKKADU — I’ve written a blog post about my journey (might still be pretty rough though): https://fbeyer.com/posts/refx-origins/

rafaeldelboni11:09:49

Whoa! Thanks I'm gonna check it out, make sure to post the link in #news-and-articles, to help more people :)

Ferdinand Beyer11:09:03

Great tip, thanks!

xlfe10:09:43

Nice blog post, thanks for taking the time to write it all down!

gratitude-thank-you 1
lilactown16:09:53

that's great to hear! glad you got over the hump and it's working out

🙌 1