Fork me on GitHub
#clojurescript
<
2020-01-26
>
dpsutton02:01:06

Reagent is funded on Clojurists Together and one of the focuses is "Supporting React hooks" . Super excited

👍 44
adz5a09:01:14

@thheller thanks for the heads up. Something lke that should be fine though (apply array (map ...) or maybe using cljs-beans ?

thheller10:01:25

the issue is that in development react "validates" the elements it gets immediately, walking the entire structure and thus forcing lazy seqs

thheller10:01:35

in production that may be delayed since it doesn't validate

thheller10:01:28

so the "work" potentially happens at different times. it is known to cause problems if you use any kind of bindings

👍 4
thheller10:01:53

but I expect it to get much more problematic once concurrent-mode gets enabled. so best to avoid it completely 😛

p-himik10:01:50

Thanks for the explanation! Is this issue wouldn't be there, would there be any reason to prefer lazy collections at all? If we exclude mere convenience due to some core functions returning lazy seqs.

thheller10:01:31

IMHO lazy seqs should always be avoided in components. messed up the entire render structure

p-himik10:01:55

Yeah, I get that. I was just wondering that maybe under some circumstances a lazy seq would not be realized completely. Maybe some implicit virtualization, dunno. But if that's not the case, then yeah, no point.

p-himik10:01:34

Thinking out loud - shouldn't Reagent then just realize all lazy seqs immediately?

thheller10:01:15

hmm it probably already does now that I think about it

thheller10:01:47

since it already turns all the vectors into react elements anyways

thheller10:01:55

yeah it might not be a problem in reagent at all

thheller10:01:44

it is a problem when things use macro or function to construct react elements

p-himik10:01:43

Yep, seems like it does that:

(defn expand-seq-dev [s ^clj o]
  (into-array (map (fn [val]
                     (when (and (vector? val)
                                (nil? (key-from-vec val)))
                       (set! (.-no-key o) true))
                     (as-element val))
                   s)))
> it is a problem when things use macro or function to construct react elements Not sure I get that. Aren't we using functions to create components all the time? Why would that be a problem?

thheller10:01:15

I said elements not components

thheller10:01:29

(react/createElement "div" #js {:className "foo"} ...)

thheller10:01:01

which frameworks that employ macros emit

thheller10:01:13

so that you don't first allocate a clojure vector and map for props

thheller10:01:23

which is then converted to the react element

p-himik10:01:49

Ah, and passing an lazy seq there would be a problem. Got it, thanks!

lilactown17:01:34

I didn't know about the diff in behavior between dev vs prod. I'll create an issue in helix for that. Thanks!

jmckitrick17:01:20

I’m looking at a re-frame subscription function, and I see something I don’t recognize:

jmckitrick17:01:20

(rf/reg-sub
  :page-id
  :<- [:route]
  (fn [route _]
    (-> route :data :name)))

jmckitrick17:01:29

What is the :<- part for?

jmckitrick17:01:22

I should add, this example project also uses reitit, if that matters.

Roman Liutikov17:01:07

That's a subscription that a current one depends on

Roman Liutikov17:01:22

The keyword is a syntax

rgm17:01:08

I think it's shorthand for this

jmckitrick17:01:06

Ok, yes, I’ve seen the chained subscriptions before, a while ago.

rgm17:01:26

I haven't found myself using it much. I've drifted into being extremely explicit with my handler definitions, having shot myself in the foot a bunch by stacking subscriptions into an L3 and using eg. (fn [sub-a sub-b ,,,] ,,,) instead of (fn [[sub-a sub-b] ,,,] ,,,) in the second fn.

jmckitrick17:01:19

I assume the benefit is some caching done by re-frame.

rgm17:01:22

I recently read the docs harder and learned the first fn can return a map of subscriptions, then you can use {:keys [,,,]} later.

rgm17:01:32

yep, automatic deduplication

rgm17:01:46

wait, not sure that's the right description

rgm17:01:57

every L2 sub (ie. the 2-arity ... supplying only one function) runs every time the app db changes

rgm17:01:51

the L3s downstream only runs when its input subs change, so this is where to hide the more expensive work

rgm17:01:04

(hopefully I've described that right)

Roman Liutikov17:01:21

it’s basically building memoized computation graph, the benefit is visible with lots of data in the db and expensive data shaping logic

dazld20:01:30

could someone point me at a simple example for running cljc tests on node with circleCI?

dazld21:01:08

answering my own q, https://github.com/metosin/malli is a good example 🙂

dazld22:01:06

having fun with symbols, in clojure, this works:

(def foo '[user/foo])
=> #'user/foo
(map resolve foo)
=> (#'user/foo)
but in cljs..
cljs.user=> (def foo '[cljs.user/foo])
#'cljs.user/foo
cljs.user=> (map resolve foo)
                 ⬆
WARNING: Can't take value of macro cljs.core/resolve at line 1
Cannot read property 'cljs$core$IFn$_invoke$arity$1' of undefined
	 (NO_SOURCE_FILE <embedded>:1077:140)
	 cljs.core.LazySeq.fn (NO_SOURCE_FILE <embedded>:1077:210)
	 cljs.core.LazySeq.sval (NO_SOURCE_FILE <embedded>:792:151)
	 cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (NO_SOURCE_FILE <embedded>:798:255)
	 cljs.core.LazySeq.cljs$core$ISeq$_first$arity$1 (NO_SOURCE_FILE <embedded>:797:366)
	 Object.cljs.core._first (NO_SOURCE_FILE <embedded>:360:89)
	 Object.cljs.core.first (NO_SOURCE_FILE <embedded>:504:173)
	 lumo.pprint.data.LumoPrinter.fipp$visit$IVisitor$visit_seq$arity$2 (NO_SOURCE_FILE <embedded>:6551:104)
	 Object.fipp.visit.visit_seq (NO_SOURCE_FILE <embedded>:6301:103)
	 Object.fipp.visit.visit_STAR_ (NO_SOURCE_FILE <embedded>:6310:506)

dazld22:01:21

guess the issue is that resolve is a macro in cljs?

andy.fingerhut22:01:36

It is a macro, and macros cannot be passed around as functions to map (nor any other functions that take functions as args.)

dazld07:01:19

Yep, the two platforms diverge, sadly. Resolve on cljs seems to assert its argument is a quoted var too, which makes its use at runtime limited.

dazld07:01:59

I’m trying to make a library cross platform.

andy.fingerhut08:01:11

I do not know the details, but vars are a place of some significant differences between clj and cljs

andy.fingerhut08:01:29

so I have heard, anyway.

Kamuela22:01:48

Is there anything like Ring for CLJS?

dpsutton22:01:55

this seems to fit the bill