This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-05-20
Channels
- # announcements (16)
- # babashka (104)
- # beginners (77)
- # bristol-clojurians (1)
- # calva (3)
- # chlorine-clover (50)
- # cider (19)
- # clojure (73)
- # clojure-australia (1)
- # clojure-europe (37)
- # clojure-france (3)
- # clojure-nl (3)
- # clojure-norway (13)
- # clojure-spec (21)
- # clojure-uk (79)
- # clojurescript (225)
- # conjure (102)
- # cursive (11)
- # datascript (1)
- # datomic (1)
- # defnpodcast (1)
- # events (3)
- # figwheel-main (2)
- # fulcro (49)
- # ghostwheel (10)
- # helix (1)
- # kaocha (17)
- # leiningen (10)
- # meander (1)
- # off-topic (26)
- # other-lisps (3)
- # pathom (5)
- # re-frame (40)
- # reagent (6)
- # reitit (33)
- # shadow-cljs (107)
- # testing (3)
- # tools-deps (68)
- # xtdb (16)
- # yada (3)
Morning, sorry for the newbie question. I am building a sign in component and my input is laggy. I looked at the docs and I think I have found a solution. Before -> Full event loop round trip
[:input.input
{:type "text"
:value @(rf/subscribe [::subs/username])
:on-change #(rf/dispatch [::events/change-username (-> % .-target .-value)])
}]
After -> Using local reagent atom
(let [username (reagent/atom "")]
(fn []
[:input.input
{:type "text"
:on-change #(reset! username (-> % .-target .-value))
}]
Is this idiomatic and normal to have state outside the db?
Is it normal to see laggy input for a regular event round trip or am I doing something wrong in the Before
bit?
Thanks :)Impossible to say anything without access to the full code. Your ::events/change-username
event handler may be non-trivial, it can have some costly interceptors, or you may have some subscription handlers that do a lot of processing. Or you may have a lot of non-trivial level-1 subs handlers. Or maybe something else.
Can you reproduce the behavior in a test app where there's nothing but that input field, that one sub, and that one event implemented trivially?
Yeah I should have clarified, that the handlers just update the db.
(defn handle-change-username [db [_ username]]
(assoc db ::state/username username))
(rf/reg-event-db ::change-username handle-change-username)
I’ll see if I can reproduce this in a test app.Consider also giving https://github.com/day8/re-frame-10x a try. It may tell you where the time is spent.
@jakob.durstberger
Do you have the option of using onblur
instead?
If you have to use onchange
then consider using dispatch-sync
which is designed for this kind of tight loop.
@U051MTYAB Even with regular dispatch
, there should be no perceivable delay, no?
dispatch
happens "very soon" (up the the browser what that means)
I don’t think I have to use on-change
it’s just the call back I found in the docs first 😄
I can try onblur
and dispatch-sync
but will only be able to do so after work.
on-blur
will make the problem disappear.
If that's an option
Because then there is no tight loop, with the user typing and events getting dispatched and then the component getting an animation-frame 16ms later.
I’d have to try. Ideally I’d want a user to be able to hit the enter key when they are still on the password field to try to sign in.
Remember also that some component libraries, like re-com already go to a bit of effort to handle this sort of issue
Of course, the component is doing A LOT, so its a bit complicated https://github.com/day8/re-com/blob/master/src/re_com/misc.cljs#L72-L181
See it in action here: https://re-com.day8.com.au/#/input-text
I found re-com a while ago and I want to create my app to be a PWA and therefore mobile first. I didn’t look further into it as it states that it doesn’t support mobile
So, summary, four possible solutions: 1. use on-blur 2. use dispatch-sync 3. user re-com (or other) 4. roll your own component which copies the sort of technique used by re-com (but is much simpler). The technique is the have local state
Any one of those solutions should work. No need to combine them.
ALSO there's nothing wrong at all with the suggestions by @U21QNFC5C ... they are good ideas .... except I'm not sure they'll get you far enough if the user types very quickly. Not sure.
Thank you all, I’ll try those today after work or tomorrow morning 🙂
If you want to go for the laziest approach you can try out: https://github.com/luciodale/fork
I just tried out dispatch-sync
and it works like a charm. I’ll definitely keep on-blur
in mind
@jakob.durstberger You should not see a performance lag in your “full roundtrip” version. Only if you have hundreds or thousands of these would we start looking at performance. I think it’s more likely you’re hit by issues with react and controlled text inputs. You should be able to google material about that. About “idiomatic”, it depends how important it is to you that your UI is 100% in sync with your DB. Things like time travel stop working with your approach above, but if you don’t want/need that you’re perfectly fine.
But to test the perf thing, try putting your subscription and on-change handler in a let, like this, that might be more efficient:
(reagent.core/with-let [sub (f/subscribe [...]
on-change #(f/dispatch...))]
[:input.input
{:type "text"
:value @sub
:on-change on-change)
})
Thanks I’ll give that a go
I have added a new FAQ: https://github.com/day8/re-frame/issues/538#issuecomment-631396325
I'm coming back to an old re-frame app, lein ancient upgraded a lot of dependencies including reagent which is now triggering warnings (e.g. reagent.core/render is deprecated). Since my app is based on the reframe-template can I just swap out the core.cljs file with the latest version of the template? (I would create a new app with the same name and options and then copy the expanded core.cljs)
Or maybe I would be better off generating a new app and copying my own code over to it?
@sandbags You may need to make these kinds of changes? https://github.com/day8/re-frame/commit/948a6010313e35a15ff8cf6889b094f861e191e2
@sandbags Depending on how many changes you made after generating from the template, it might still be worthwhile regenerating from the template and copying in your code.
We have been doing a bit of work on the re-frame-template to make it work better with shadow-cljs
Hi there. I’m trying to use re-frame-10x
with existing re-frame app, but getting an exception at the moment of rendering root component:
TypeError: Cannot read property 'call' of undefined
at re_frame_10x.cljs?rel=1590003075265:29
which points to this chunk of code:
(trace/with-trace {:op-type :render
:tags (if-let [component-name (component/component-name c)]
{:component-name component-name}
{})
Noob Q: Is there an “approved” way of partitioning the app-db
to separate ephemeral state (navigation state) from durable state (domain data, possibly shared) such that ephemeral is in-memory only, but durable can be backed by something like re-frame-firebase
(https://github.com/deg/re-frame-firebase)? Or am I thinking about this wrong?