Fork me on GitHub
#re-frame
<
2019-01-01
>
caleb.macdonaldblack05:01:31

Is the performance gain for creating subs once in form-2 components worth the extra code? It works fine with simple subs, but when I need to sub to an id and then pass that id into other subs it all goes to shit. Perhaps the pattern of subbing to an id and passing into another sub is a bad idea. Perhaps its fine to re-create the sub on re-render and there isn't much of a performance hit. perhaps there is another way to achieve this without recreating the sub on re-render. Anyone have any ideas?

caleb.macdonaldblack05:01:45

I usually use the id pass through pattern as I'm iterating over a list of ids and then passing each one into the subs

WhoNeedszZz06:01:17

I'm having trouble getting live reloading to work properly with re-frame and Shadow CLJS. It's reloading the code, but not refreshing the component that got changed. What am I missing in my configuration?

caleb.macdonaldblack06:01:45

send code of the component

caleb.macdonaldblack06:01:56

Could be a form 2 not correctly setup

WhoNeedszZz06:01:07

It's any component I have

caleb.macdonaldblack06:01:23

is it a form-1 or form-2?

WhoNeedszZz06:01:55

And a React Fragment

caleb.macdonaldblack06:01:44

Are you using the actual React fragment component?

WhoNeedszZz06:01:06

I'm using [:<>]

caleb.macdonaldblack06:01:16

ah okay that's fine

WhoNeedszZz06:01:26

But not in a fn

caleb.macdonaldblack06:01:42

How are you changing your component? updating a value in app-db? then subscribing?

WhoNeedszZz06:01:43

It's a pure ui element

WhoNeedszZz06:01:01

No, just updating the p component

WhoNeedszZz06:01:15

Does it have to go through app-db for that to work properly?

caleb.macdonaldblack06:01:24

and hard reload works?

WhoNeedszZz06:01:35

If I refresh the page the component is correct

caleb.macdonaldblack06:01:11

do you have :after-load set up in :devtools in shadow-cljs.edn?

WhoNeedszZz06:01:32

Not sure what you mean so no

WhoNeedszZz06:01:43

I'm using lein btw

caleb.macdonaldblack06:01:36

after-load is called on refresh. The reruns mount-root which calls rerender in reagent

WhoNeedszZz06:01:43

oh nice. Thanks

WhoNeedszZz06:01:48

I knew it was something trivial

caleb.macdonaldblack06:01:07

Yea it's happened to me heaps

caleb.macdonaldblack06:01:25

does that work for you now?

WhoNeedszZz06:01:30

Still have to refresh the page

caleb.macdonaldblack06:01:50

is your rerender function for reagent called mount-root?

caleb.macdonaldblack06:01:07

it actually doesn't need to be. As long as the symbol matches up

WhoNeedszZz06:01:19

I went with the lein template

caleb.macdonaldblack06:01:56

What does your mount-root code look like?

caleb.macdonaldblack06:01:32

and what does your shadow-cljs.edn look like?

WhoNeedszZz06:01:54

That's in project.clj

WhoNeedszZz06:01:11

Well I feel dumb

WhoNeedszZz06:01:21

It did need to be in shadow-cljs.edn

caleb.macdonaldblack06:01:43

ah okay. Makes sense I was confused about that too.

WhoNeedszZz06:01:45

I thought that since when you set :lein true it would use the build config in project.clj, but I guess it completely ignores that

WhoNeedszZz06:01:05

So I guess I'm not sure what it does read from project.clj

caleb.macdonaldblack06:01:08

:lein true makes it use the deps from lein only afaik

WhoNeedszZz06:01:28

So should I just nuke the :cljsbuild section?

caleb.macdonaldblack06:01:13

For example that's what my project.clj looks like with shadow-cljs

WhoNeedszZz06:01:20

I'm still using profiles

WhoNeedszZz06:01:28

So dev deps are separate

caleb.macdonaldblack06:01:50

oh yea that should be all fine

WhoNeedszZz06:01:53

Lots of updates to those versions btw

WhoNeedszZz06:01:17

And thanks for inadvertently suggesting an http lib

WhoNeedszZz06:01:22

I'll need that to set up Stripe

caleb.macdonaldblack06:01:03

I use that because I put my http layer behind protocols

caleb.macdonaldblack06:01:59

I don't use it because I want to decouple my http layer from re-frame but not everyone does it that way

WhoNeedszZz06:01:06

Decouple for what specific purpose?

WhoNeedszZz06:01:37

Btw I went with bidi+pushy instead of secretary

caleb.macdonaldblack06:01:57

Mainly to keep the concerns of dealing with a http api away from my business logic in the web app.

WhoNeedszZz07:01:00

What does the rest of your shadow-cljs.edn look like?

WhoNeedszZz07:01:33

Oh, I'm just generating the token on the web app and then sending the token to my backend server as per the Stripe docs

WhoNeedszZz07:01:39

So I just need to POST

WhoNeedszZz07:01:05

So no production build?

caleb.macdonaldblack07:01:24

shadow-cljs release app

caleb.macdonaldblack07:01:46

That does a production build.

WhoNeedszZz07:01:54

Ah, well that's a little simpler

WhoNeedszZz07:01:02

So it automatically sets the options

WhoNeedszZz07:01:07

Double edged sword though

WhoNeedszZz07:01:59

Like changing :optimizations for a min or test build

WhoNeedszZz07:01:02

Which I haven't used yet

WhoNeedszZz07:01:10

What's that from?

caleb.macdonaldblack07:01:08

I think by default release does :advanced compilation.

caleb.macdonaldblack07:01:32

I used to have different build so I can pass in different keys for staging, prod & development releases. However I use actual environment variables at compile time for that now

caleb.macdonaldblack07:01:40

And I bring them in with a macro

WhoNeedszZz07:01:50

Hmm ok. So you'd have to enable infer-externs for advanced to work

caleb.macdonaldblack07:01:20

Afaik shadow doesn't need externs at all

caleb.macdonaldblack07:01:57

I could be wrong though I'm not too sure

caleb.macdonaldblack07:01:37

I never have to deal with externs. I use https://github.com/binaryage/cljs-oops to interop with js

WhoNeedszZz07:01:50

Btw do you know how to get rid of the "cljs.core/-, all arguments must be numbers, got [#{nil clj-nil} number] instead" warning from zprint/focus.cljc?

caleb.macdonaldblack07:01:20

Nah I don't get warning

WhoNeedszZz07:01:34

I'm not sure what's bringing that in

caleb.macdonaldblack07:01:40

Ah okay. in oops my syntax is pretty much (oops/ocall x "baz"). And because you're using strings not symbols you don't need to worry about anything getting munged in advanced comp. Dealing with externs was a pain in the ass. This was before I starting using shadow-cljs though

WhoNeedszZz07:01:40

Yeah, luckily I haven't messed with ClojureScript enough up til now so I haven't experienced those woes

mikethompson10:01:38

@caleb.macdonaldblack Checking: when you say " it all goes to shit" ... you are talking about performance, right? Checking: for case 1, Style A and Style B should have the same performance, true? The cost of recreating an existing subscription should be tiny. Checking: should line 27 be @foo-id or just foo-id? I assume the later.

caleb.macdonaldblack10:01:02

Sorry "it all goes to shit", I'm referring to that the code becomes really hard to write. I have to create children components to get it to work without creating subs in the render code

caleb.macdonaldblack10:01:37

For your third comment, the later is correct

caleb.macdonaldblack10:01:21

and "for case 1, Style A and Style B should have the same performance, true?" This is pretty much my question. Is it efficient to create subs in the render section of a component. I'm hoping so, because components become a lot easier to write. I wasn't sure if there was much overhead in re-creating the sub every time.

mikethompson10:01:07

Is there a large number of these components?

mikethompson10:01:45

In that case Style A and Style B are essentially the same

caleb.macdonaldblack10:01:02

Do you think the same can be said for anonymous functions? Such as #(rf/dispatch [:foo])?

caleb.macdonaldblack10:01:21

re-created on each render?

mikethompson10:01:22

There is very little cost to "recreating" an already existing subscription

mikethompson10:01:55

They are cached. So its the cost of a map lookup

mikethompson10:01:40

Yes, DOM event handlers can sometimes cause unnecessary rendering

mikethompson10:01:15

Because this evaluates to false (= #(rf/dispatch [:foo]) #(rf/dispatch [:foo]))

mikethompson10:01:42

Ie. the DOM event function we create this time will not test equal to the one we created last time

caleb.macdonaldblack10:01:31

So would it be best to move them out of the rendering and just use references/symbols?

caleb.macdonaldblack10:01:36

Awesome thank you. Also lastly do you think looping over ids and passing them into subs/events is a good idea in general? It seems to work okay when the db is the only input signal. However for subs that have multiple input signals that need the id it becomes a pain.

mikethompson10:01:34

That document has some advice

caleb.macdonaldblack10:01:36

Sorry to clarify that's multiple levels/depth of input signals

mikethompson10:01:08

And consider using re-frame-10x to get insight into what is happening and why

👆 5
caleb.macdonaldblack10:01:25

Okay thanks. That doc and re-frame-10x is very helpful. I'll definitely look into that right away. :thumbsup:

WhoNeedszZz10:01:27

Thanks for making 10x. It's super helpful!

mikethompson11:01:55

Thanks. I wish we had more time to do more on it.

mikethompson11:01:08

There's still a lot of untapped potential

WhoNeedszZz11:01:16

Any idea what this warning is about? "Warning: unmountComponentAtNode(): The node you're attempting to unmount was rendered by another copy of React."

WhoNeedszZz11:01:25

I might just be seeing it when it live reloads incomplete code

Kelly Innes15:01:28

Interesting! I've never seen that when working with JS React, but it could be something about the hot reloading

herald22:01:03

does anybody know how to give a CSS style property multiple values, with re-frame's hiccup?

image-rendering: -moz-crisp-edges;
image-rendering: -webkit-crisp-edges;
image-rendering: pixelated;
image-rendering: crisp-edges;
Since hiccup uses a map, I'm not allowed to have duplicate keys

lilactown23:01:49

@regen you won’t be able to do this with reagent (and by extension, re-frame) directly

herald09:01:27

thanks for the response! I guess I just gotta bite the dust and write some CSS or pull in a CSS lib

lilactown23:01:52

you’ll need to use CSS