helix

https://github.com/Lokeh/helix
Aron 2020-05-04T07:24:47.118500Z

I just realized that something that was simple in js, I don't know how to do it in clojurescript

Aron 2020-05-04T07:26:48.119700Z

anyone uses shadow-cljs? is there a way to hack the dependencies so that helix when requires react and react-dom, I can instead specify a different version for it to use? 🙂

Aron 2020-05-04T07:27:41.120400Z

I want to use helix with https://reactjs.org/docs/concurrent-mode-adoption.html I am not very happy about this separation of versions, but what to do

orestis 2020-05-04T07:31:25.120900Z

With shadow-cljs, you just use npm for all that.

orestis 2020-05-04T07:31:46.121200Z

Helix (from what I can see) doesn’t bring that in for you

orestis 2020-05-04T07:31:54.121400Z

https://github.com/Lokeh/helix#shadow-cljs-and-npm

Aron 2020-05-04T07:34:12.122300Z

"all that", "that", I find it hard to understand what "that" exactly is in each case : ) Could you elaborate please?

Aron 2020-05-04T07:34:50.122600Z

the thing is that I have 3 separate version of react installed

Aron 2020-05-04T07:35:05.122900Z

so it would be nice if I could tell helix which one to use

orestis 2020-05-04T07:53:39.123900Z

Helix doesn’t come into it - it’s shadow CLJS which uses whatever is in node_modules

Aron 2020-05-04T07:58:28.125200Z

of course it does, it requires react to be installed under the name react

Aron 2020-05-04T07:59:01.125900Z

it's another thing that shadow-cljs provides this under the name of react, but if it wouldn't be a predefined name, it would be nicer, so I could have whatever version used

Aron 2020-05-04T08:04:02.126600Z

since otherwise I would have to constantly update the build config for something that is business logic in this case, which version I am demoing

Aron 2020-05-04T08:04:13.126900Z

and I hate the semantic web more and more

Aron 2020-05-04T08:04:26.127200Z

it's prescriptivist through and through

Aron 2020-05-04T09:36:02.128400Z

so, I am getting errors with the experimental build, and I am not sure why. Has anyone tried to use helix with react@experimental before?

lilactown 2020-05-04T15:44:19.128600Z

yes, I have

lilactown 2020-05-04T15:44:59.129200Z

as for using helix with a package of a different name than React, I’m not sure how to support that

lilactown 2020-05-04T15:46:46.129800Z

if you post the error you’re seeing I might be able to help you 🙂

lilactown 2020-05-04T15:47:16.130500Z

most errors are due to installing mismatching versions - e.g. you install react@experimental but don’t install react-dom@experimental and react-refresh@experimental (if you’re using react-refresh)

lilactown 2020-05-04T15:51:15.131300Z

FWIW install the experimental versions should just work - there’s no additional config required. if you for some reason want multiple versions of React on the same web page at the same time, I don’t know how to do that

alidlorenzo 2020-05-04T16:57:47.132400Z

You can alias package names with shadow-cljs, e,g., I use it for react-native-web:

:js-options {:resolve    {"react-native" {:target :npm                                                     
                                          :require "react-native-web"}}}

Aron 2020-05-04T18:50:42.133600Z

not using refresh I think, but will check

Aron 2020-05-04T18:51:22.134400Z

@alidcastano that does work but it works for all packages overall the same way, can't specifically resolve different versions for different dependencies

Aron 2020-05-04T19:00:03.135600Z

one thing I would like to ask a bit of help before I go back to the experimental build, is how to use the progress channel of cljs-http with helix. Is there an idiomatic way to read in a use-effect or something from the channel?

Aron 2020-05-04T19:00:18.136Z

basically, writing while(true) seems weird, even in a use-effect

Aron 2020-05-04T19:00:23.136200Z

I am not sure if it will work 😄

alidlorenzo 2020-05-04T19:34:25.136400Z

@ashnur i don’t think you’d ever want two* versions of react running at same time. specially with hooks, that will cause nasty errors

alidlorenzo 2020-05-04T19:34:48.136900Z

just set the necessary alias per build

alidlorenzo 2020-05-04T19:37:22.137200Z

if you need a useEffect to run every time just don’t pass dependencies array as second argument

Aron 2020-05-04T19:42:00.137700Z

don't tell me what I want

Aron 2020-05-04T19:42:09.138Z

: )

Aron 2020-05-04T19:44:04.138100Z

That's not an answer to my specific question. I get how react works, I have trouble using cljs http channels

Aron 2020-05-04T20:31:47.140100Z

also, I don't want to use different react versions TOGETHER, I want to use them in the same app. That's not together. : ) but I have since got help in #shadow-cljs that it's better to have separated builds, so I completely given up on that idea, I will not complicate my life by fighting the tooling. (It's worth mentioning though how limiting is when people assume they know what others want or might or might not want : D)

lilactown 2020-05-04T20:45:45.140600Z

there are several ways you could use core.async channels with hooks

lilactown 2020-05-04T20:45:48.140800Z

depending on your use case

lilactown 2020-05-04T20:48:34.142900Z

I’d have to think more about it. for one-shot requests you might be able to do:

(let [[response set-response] (hooks/use-state nil)]
  (hooks/use-effect
    :once
    (go (-> (<! (http/get "api"))
            (set-response))))
  ,,,)
            

lilactown 2020-05-04T20:49:00.143100Z

ah, the progress channel, sorry

Aron 2020-05-04T20:49:43.143300Z

🙂

Aron 2020-05-04T20:50:05.143900Z

I am using take! and put! from onChange and onClick at the moment

Aron 2020-05-04T20:50:29.144400Z

simpler than setting up a go loop, but probably not what I should use for the progress events

lilactown 2020-05-04T21:02:53.149700Z

(defhook use-take
  [channel on-take]
  (let [cancel-signal (hooks/use-ref false)]
    (hooks/use-effect
     [channel on-take]
     (go-loop []
       (if-not @cancel-signal
         (do (on-take (<! channel))
             (recur))
         (reset! cancel-signal false)))
     #(reset! cancel-signal true))))

lilactown 2020-05-04T21:03:09.150Z

something like that

Aron 2020-05-04T21:23:29.150400Z

wow, thanks, that's very detailed!

Aron 2020-05-04T21:25:27.150800Z

the last line is the return function to run on unmount in react?

Aron 2020-05-04T21:26:00.151100Z

trying to figure out where mounted? will play a picture

Aron 2020-05-04T21:26:15.151400Z

in any case, this is enough to solve it, thanks again

lilactown 2020-05-04T21:36:54.151700Z

ah sorry, I forgot to remove mounted? it was part of an earlier draft

lilactown 2020-05-04T21:37:23.152300Z

yeah, in use-effect you can return a function that runs when the dependencies change, or the component is unmounted

lilactown 2020-05-04T21:37:29.152500Z

it’s a “cleanup” function for the effect

lilactown 2020-05-04T21:39:02.152800Z

note I haven’t tested that at all 😄 so might not quite work. but it’s the general idea

Aron 2020-05-04T21:48:27.153600Z

it's very useful, i was looking for some proper way to loop only when actually something happens, I just need to read the docs about these functions

Aron 2020-05-04T21:48:46.153900Z

I almost never use loops, just lazy seqs

Aron 2020-05-04T22:44:58.157Z

Ok, so I don't get the else clause for the if-not. That should only ever be true after the hook was unmounted, but at that point I just want it to be garbage collected, a new element mounted will use a new hook anyway. In fact, what I would rather do somewhere is to check if the channel is closed and escape the loop then

lilactown 2020-05-04T22:51:34.157700Z

yeah, the else clause is there to cleanup when either the channel changes, the on-take function changes, or the component unmounts

lilactown 2020-05-04T22:52:07.158300Z

if it hits that branch, then it’s because the effect has run the cleanup function

lilactown 2020-05-04T22:52:45.159100Z

but the go-loop will still be running, which is why we check for the cancel-signal and if it’s true, don’t recur

lilactown 2020-05-04T22:53:49.160200Z

for example, if we naively did

(go-loop []
      (do (on-take (<! channel))
          (recur)))
then even once the effect cleaned up, it would still be running the go-loop and it wouldn’t be garbage collected

Aron 2020-05-04T22:54:07.160600Z

I don't understand what it achieves to set the cancel-signal back to it's initial value

Aron 2020-05-04T22:54:56.161200Z

maybe it's a typo and should be true? but then it would never reach that clause

Aron 2020-05-04T22:56:35.161800Z

https://gist.github.com/ashnur/c336b998fbc5d7c7580aa52fe9e827f7 this is how I would expect it to work naively 🙂

lilactown 2020-05-04T22:57:16.162300Z

I’m not completely sure if I did that right

lilactown 2020-05-04T22:57:33.162900Z

my thinking was that, if you pass in a new on-take function, you want to stop your go-loop and start another go-loop using the new function

Aron 2020-05-04T22:57:35.163Z

I know exactly the feeling : )

lilactown 2020-05-04T22:58:20.164100Z

so in that case, you want to have your current go-loop see the cancel-signal, and then reset it so the new one will start

lilactown 2020-05-04T22:58:25.164400Z

but I might have done it wrong

Aron 2020-05-04T22:58:27.164500Z

calling the use-take hook a second time should create a new loop entirely imho, it's a new scope, new context, new bindings

lilactown 2020-05-04T22:58:34.164700Z

it’s not calling it a second time

Aron 2020-05-04T22:58:54.165400Z

with a different argument should mean a different call?

lilactown 2020-05-04T22:59:07.165700Z

think about like if you take a function as a prop, and the function changes

lilactown 2020-05-04T22:59:19.166Z

or if it depends on some state

lilactown 2020-05-04T23:01:18.168200Z

(defnc my-component
  []
  (let [[state set-state] (hooks/use-state "")
        on-take (fn [chan-value]
                  (println "current state is:" state "and channel value is:" chan-value))]
    (use-take some-channel on-take)))

Aron 2020-05-04T23:08:22.169300Z

I think this topic deserves more examination : D I tried to find clojurescript + react/hooks + channels examples online but I only found your hooks/cljs examples, nothing much else.