This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-09-21
Channels
- # alda (1)
- # bangalore-clj (1)
- # beginners (7)
- # boot (88)
- # carry (2)
- # cider (8)
- # cljs-dev (60)
- # cljsjs (2)
- # cljsrn (45)
- # clojure (255)
- # clojure-belgium (5)
- # clojure-boston (1)
- # clojure-dusseldorf (3)
- # clojure-greece (49)
- # clojure-italy (10)
- # clojure-russia (30)
- # clojure-spec (78)
- # clojure-uk (11)
- # clojurebridge (1)
- # clojurescript (80)
- # cursive (14)
- # datomic (33)
- # defnpodcast (4)
- # devcards (2)
- # dirac (15)
- # editors (23)
- # emacs (5)
- # events (11)
- # funcool (1)
- # hoplon (1)
- # juxt (1)
- # luminus (2)
- # mount (7)
- # off-topic (15)
- # om (152)
- # om-next (2)
- # onyx (17)
- # parinfer (1)
- # proton (38)
- # re-frame (35)
- # reagent (110)
- # rum (3)
- # spacemacs (3)
- # specter (51)
- # test-check (2)
- # testing (5)
- # untangled (234)
Hi I am new to reagent / clojurescript so apologies if this is a dim question
I am using bidi/accountant for managing client side routing as per https://pez.github.io/2016/03/01/Reagent-clientside-routing-with-Bidi-and-Accountant.html
It works basically by having a function 'home' that listens to the session for changes to the route:
(defn- home [state]
(let [route (session/get :route)
page (:current-page route)]
(page-contents page)))
and renders the page calling the multimethod page-contents
So I have a component like
(defmethod page-contents :foo []
[:a {:href (bidi/path-for routes :bar)} "link"])
and it works fine, but if I have the same component but returned as a function:
(defmethod page-contents :foo []
(fn []
[:a {:href (bidi/path-for routes :bar)} "link"]))
Then when I click on the link the url in the browser changes but the home function doesn't register the change to the session and re-render the page
I can see that accountant / bidi are working as expected and the session is being updated.
but the home function doesn't seem to 'notice'
any thoughts on what the difference is here ?
@gingerwizard: Strange indeed. In the project I am working with almost all the page components return a function. Do you get any errors/warnings in the console?
@pez well yes this is the thing - most of my components will need to be like that
no errors in console and I can see accountant/bidi setting the session state
and the url is changing as expected
it seems so fundamental that I must be missing something
I think it might be an error in the example that gets visible when you return the component as a function...
@gingerwizard: What if you include the doc string? (Before the lambda)
Forget that with the doc string… Now I can reproduce the problem in the example app. When I click once more on the link I get a full app reload.
@pez I don't see the app reload behaviour
add more logging everywhere; my guess is that there's a mistake or conceptual misunderstanding somewhere
I don't think defmethod vs defn should make a difference
also (defn x [] [:div])
should be exactly equivalent to (defn x [] (fn [] [:div]))
@pesterhazy I have added logging up to the point that the 'magic' happens
in my repl I can see the state of the session is what I would expect
not sure how to debug the interaction of the session and the reagent component ?
can you say in 1 sentence what you expect to see and what you actually see?
so I expect to see: accountant gets a bidi match on the url and pushes the route into the session
(this happens as expected)
"session" is an "accountant" concept?
a reagent session
i.e. as I understand it just a ratom ?
you meant the global state atom?
ah ok
then I expect the function page which derefs the session to "see" that the route has changed and call the multimethod
why not add logging to the render fn that derefs the ratom?
yeah I have - not called
ok; can you try manually swap!
ping the atom?
(e.g. using a button that does that)
yes I have and that doesn't work (done via cljs repl)
it's like the component has stopped listening
so it sounds like the issue is simply that you have a component that derefs a ratom and is visible but doesn't get rerendered when you swap the ratom, correct?
yes I think so
- check that it's actually a ratom (not clojure.core/atom)
but as I say - works when I return [:a {:href... but not (fn[] [:a {:href
so the only difference is that
that sounds like a red herring to me
can you turn it into a defn?
and see if that works
you mean turn the multimethod into a defn and call ?
defmulti+defmethod is equivalent to a defn with a cond
sure - just checking what you mean -
hmm ok that looks like it has made a difference
so I replaced (defmulti page-content :foo [] (fn[] [:a ...
with (defn foo[] (fn [] [:a ...
and called that - and I see that the component that derefs the session spots the change
that's interesting
might be a bug in reagent
there's a test for it here: https://github.com/reagent-project/reagent/blob/c980ac0c3d19ae94450655afde49d1218d9f0854/test/reagenttest/testreagent.cljs#L315
are you on a recent version of reagent?
yes 0.6.0-alpha
I'm beginning to confuse myself a bit - gonna have a cup of tea and come back and see if I am doing something really stupid
it could be that reagent checks if the fn meets certain conditions
e.g. implements IFn
maybe that check doesn't work properly for defmultis
might be worth wrapping the defmulti in a defn to see if that works
(defn foo* [] (foo))
might also be a new issue with 0.6.0 for all we know
OK - so I might have a step forward
if I define my component like this
(defn home []
(fn []
(let [page (:current-page (session/get :route))]
[page-contents page])))
it does pick up the change in the session (the rendering doesn't seem to work but maybe that's a different problem)
based on the example I was copying I was using this
(defn home []
(fn []
(let [page (:current-page (session/get :route))]
(page-contents page))))
so with logging in that function I can see the route change in the session and home getting called
it doesn't actually render the new route though so that's another issue
OK have run @pez example that I copied in the first place and it exhibits the same behaviour
OK I have it
it is multimethod madness
2 changes to get it all working I think @pez
1 use [] not () for calling page-contents
2/ ^{:key page}
so in your page func
^{:key page} [page-contents page]
the stackoverflow question explains all I think
Bottom line: because of the caching, multimethods won't work very well, unless you find a way to completely blow up the component and start again, which is what the currently-top-voted approach does: ^{:key @current-route} [pages @current-route] Of course, blowing up the component and starting again might have its own unwelcome implications (depending on what local state is held in that component).
I wonder what makes it work in the project I work on. (I mainly dab with svg things and my colleagues are the clojure experts.)
yeah now that is strange
Since posh is involved maybe there are more things that can trigger the reaction. In any case now I am a bit worried this caching thing is luring in the background ready to bite us. 😄
well thanks for your help @pez and @pesterhazy better get on with some real work now...
@gingerwizard that's a crazy issue
still haven't fully understood why this fails
@pesterhazy yeah pretty funky
Hi, I'm struggling with a controlled input that parse its content: the user is able to enter a list of tag separated by commas "stuff,tag,hello" I would like to use the onChange handler to update my state with the parsed content (split input-value ",") so I get a vector on my state. The problem is that I can't synchronize properly with the :value of the input because if I type "hello," the comma wont appear because it's splited then joined again How do you handle this ?
Using defaultValue helps but then I have other issues. Storing the raw input value in the state would work but feel wrong as other parts of the app need this state and should have a vector directly
only the input itself would need to access the raw value, everything else could use the parsed one
That's the only thing I didnt try. Should work in my case
thanks