helix

https://github.com/Lokeh/helix
2021-05-24T13:41:49.018700Z

This might be a silly question (apologies - I’m new to clojurescript, coming from a python background), but what are the benefits of using helix instead of just reagent?

Aron 2021-05-24T14:41:34.022100Z

As someone who used helix for many months now but never tried reagent, my reasoning was that this way I can use react state management and any react developer can understand the code, if they squint a bit 🙂 Even though possibly the state management tooling provided by the core of clojurescript is one of the biggest value propositions, having to sell all of it at once to my bosses would've been more difficult. And I wasn't very experienced with cljs.

lilactown 2021-05-24T16:54:15.022700Z

yep, like Aron said, helix is very close to React. Reagent adds a bunch of stuff on top

lilactown 2021-05-24T16:54:51.023500Z

both are fine choices. reagent has a lot more discussion, blog posts, and usage in the ClojureScript world. if you're new to both ClojureScript and front end development, it might be easier to get help

lilactown 2021-05-24T16:55:12.024Z

however, if you're already familiar with front end development using React, helix should make it very easy for you to jump in, learn the syntax and start building UIs

2021-05-24T19:38:58.028200Z

awesome, thanks @ashnur and @lilactown. So if I understand this correctly, Helix is more like React, and Reagent is more idiomatic clojure. I kinda like the idea of having something that almost looks like React, but that interfaces well with Clojure. The only shortcoming I see for Helix right now is that it doesn’t have super straightforward interop with re-frame, which is arguably the most popular state management framework for clojurescript. I looked at the hooks on github but it’s a bit confusing (at least for a noob) on how those hooks exactly work, so I haven’t managed to make re-frame work with helix (yet).

Aron 2021-05-24T19:43:29.028700Z

I am also a bit confused by the situation. In theory there is a use-subscription hook somewhere, but I think that's only experimental?

Aron 2021-05-24T19:43:45.029100Z

Or uses pre-Fiber assumptions

raspasov 2021-05-24T19:48:45.031700Z

I’ve been using React/ReactNative since 2014 or so. I’ve seen a number of libs/frameworks/state management approaches come and go, both in CLJS and JS world. I think sticking as close to React as possible makes sense (to the point where I don’t use any libraries at all, I just use direct JS interop with React and have my own basic state management on top). If I’m forced to pick a library today, Helix would be my choice.

jimmy 2021-05-24T19:52:19.034600Z

One less than great thing about trying to combine reframe and helix is that you will end up with both helix and reagent in your application. For a production application that is probably less than desirable

1👀
raspasov 2021-05-24T19:52:30.034700Z

I think using React directly + using basic Clojure(Script) constructs is an underappreciated option. It does require very good expertise and understanding of both React and Clojure(Script), perhaps that’s why.

wilkerlucio 2021-05-25T19:42:28.041100Z

I can also see oportunities to do dynamic batching, like Falcor does https://netflix.github.io/falcor/

wilkerlucio 2021-05-25T19:43:18.041400Z

the basic idea is to debounce the API requests, so you can accumulate items and send a single request, would be interesting to see how much we can optimize/combine those with EQL

wilkerlucio 2021-05-24T19:56:52.036Z

I think if I were to use react directly, I would end up writing very similar helpers, so since @lilactown already took the work, I use it 🙂

1❤️3👌
raspasov 2021-05-24T19:57:25.036500Z

That’s fair, but esp. around hooks, I think just using interop is super basic.

wilkerlucio 2021-05-24T19:57:51.036700Z

one thing to consider here is that DCE is quite good in CLJS, this means you can use reframe, but use just the hooks helpers from Helix, this way you pay a very low price on it, in fact, only what you use

raspasov 2021-05-24T19:58:45.036900Z

(def use-effect (.-useEffect React))

(use-effect 
 (fn []
  (fn cleanup []
   )))

raspasov 2021-05-24T19:58:58.037100Z

What kind of wrapper do you really need here 🙂

wilkerlucio 2021-05-24T19:59:44.037300Z

when you have a cleanup, I think looks good, but this botters me:

(def use-effect (.-useEffect React))

(use-effect 
 (fn []
    (do-something)
    js/undefined))

raspasov 2021-05-24T19:59:47.037500Z

Not familiar with the js/undefined case. Which hook does that apply to?

wilkerlucio 2021-05-24T20:00:00.037700Z

because if you don't return js/undefined, React complains that you can only return a fn from a effect

wilkerlucio 2021-05-24T20:00:36.037900Z

this is because of JS vs CLJS different, in JS, if don't use return on a fn, you get undefined as the return, but in CLJS it will return the value of the last expression

wilkerlucio 2021-05-24T20:00:53.038100Z

which, if it is anything other than a fn, or js/undefined, will throw an error from React

jimmy 2021-05-24T20:02:46.038300Z

Yeah, I suspect in practice though you may run into more issues than just code size. Closure dead code elimination is definitely great. But you will also potentially have conflicts with dependencies. You could have confusion on a team about which way things ought to work. etc. Definitely not suggesting don't do it at all. Just that is probably worth thinking through and really testing out what it is like in practice before making the decision. Also, though, if people really like reframe and those people also want to use helix, making a reframe like library is a great opportunity for someone.

1
raspasov 2021-05-24T20:04:21.038500Z

Hmm, I’ve always been returning a cleanup fn.

raspasov 2021-05-24T20:04:39.038700Z

(for that past few months since I started using hooks and useEffect)

raspasov 2021-05-24T20:05:36.038900Z

I guess that’s how I avoided running into that case, I always put an empty (fn cleanup []) even if it did nothing.

raspasov 2021-05-24T20:09:53.039200Z

FWIW, my whole medium-sized project has only 4 (useEffect …) usages. I try to keep any side-effecting stuff out of the components as much as possible.

wilkerlucio 2021-05-24T20:18:27.039400Z

I do use a lot of effects to integrate foreign libraries, like Cytoscape graph renders, D3 integration, CodeMirror integration, for those effects are super handy 🙂

raspasov 2021-05-24T20:24:10.039800Z

Yes, I think those are good use cases. Mostly non-IO related stuff. If people start putting HTTP calls, etc in use-effect I think it’s not good.

wilkerlucio 2021-05-24T20:35:22.040Z

I used to think like that in the past, but nowadays I'm starting to think it can be good, and the Suspense + Async Rendering seem like something that will favor this kind of approach. my long time as a Fulcro usermade me aware of advantages and how we can reduce the number of requests. but at same time I feel the pain of *needing* to connect every component in the same query. so I'm excited with Fulcro Raw, which allows some effects to tap into the app state, and they may also trigger IO in the middle, I have coded a few projects playing with that, and I quite enjoy the results, I can develop really fast, and if I see the number of IO going off the rails, Ican always refactor, connect some queries and move the IO up.

wilkerlucio 2021-05-24T20:35:52.040200Z

still feels experimental, but I have big hopes with this path of "ui tree processing"