Fork me on GitHub
#re-frame
<
2015-08-13
>
pupeno09:08:06

How do I deal with a handler depending on another. Something like having a handler called get-user that request the user from the server, another got-user, that gets the data and puts it in the state, but now I have one called get-friends. Get-friends should only be run after get-user/got-user finished but I don’t want got-user to run get-friends as it’s not needed most of the time? Should get-friends do a dispatch-sync of get-user?

profil10:08:14

@pupeno: You can dispatch several times?

pupeno10:08:42

profil: what do you mean? I guess the answer is yes, but I don’t see how that helps.

profil10:08:39

get-friends dispatches get-user/got-user and then dispatches itself

pupeno10:08:24

How do I wait for got-user to run to then dispatch itself?

profil10:08:25

@pupeno: ahh, I guess you would have to dispatch it from got-user then, you could parameterize it

profil10:08:37

or use dispatch-sync, which is a hack 😄

pupeno10:08:52

profil: but got-user is used in every single page while I want to fetch the friends only in one page.

pupeno10:08:59

dispatch-sync can’t be used inside a handler

pupeno10:08:43

Every piece of information fetched from the server will depend on the user, which means that if I fetch that information in got-user, got-user will downloading a humongous amount of data that will mostly not be used.

pupeno10:08:06

I could pass around next-handler but it feels like continuations, which are hard to debug, and I bet I’m not the first one to deal with this. I could copy code, but then I think I’ll end up with a lot of duplication.

profil10:08:43

dispatch itself then, until you have got a valid user, in get-friends (when (nil? (:user db)) (dispatch [:get-friends]))

pupeno10:08:32

Do you mean:

pupeno10:08:53

(if (nil? (:user db)) (do (dispatch [:get-user]) (dispatch [:get-friends])) (ajax-call-to-get-friends))

pupeno10:08:57

Ah, that’s better.

pupeno10:08:18

It still feels a bit convoluted… for example, if I have 5 or 6 sequential calls.

profil10:08:24

why would you have 5 or 6 sequential calls?

pupeno10:08:58

I don’t know yet as I haven’t build a complex SPA before, but my server apps got complex enough where we needed to interact with 10 different models or more in a single render. I can see that turning into several requests to the server API.

shaym11:08:36

what is the correct way of having a parent component P conditionally display child component A or child component B (based on atom data and secretary route), when i switch from one state to the other the view does not get updated properly?

escherize11:08:12

(defn p []
  (let [a-or-b-state (subscribe [:something-important])]
    (fn []
      (if @a-or-b-state
        a
        b))))

shaym11:08:18

escherize: have a look at the paste, i think i am using the exact same approach , bbut the view only updates the first time

shaym11:08:32

after that , i get partial updates or none at all

escherize11:08:34

as this: (defn p [state] (if @state a b))

escherize11:08:50

do you mean for project-page?

shaym11:08:45

[body-main]

shaym11:08:58

is the parent component

escherize11:08:02

I would try wrapping your page-function on line 28 with []'s

shaym11:08:19

Uncaught Error: Invalid arity: 1

shaym11:08:29

after wrapping with vector

escherize11:08:29

It's hard to troubleshoot without more context

shaym11:08:04

yep i have been struggling with it for a few hours

antishok11:08:29

@shaym: i think page-function needs to either be a reaction, or it needs to be in the render part of a form-2/3 component

shaym11:08:51

@antishok: i was also wondering if i need the 3rd form (create-class) ?

antishok11:08:07

form-2 is enough here i think

shaym11:08:15

making page-function a reaction seems easier, ill try it

shaym11:08:47

you think that form 2 without another reaction will work, or it needs the page-function reaction

antishok11:08:05

i think you should make body-main a form-2 anyway

antishok11:08:16

even for page that's needed

antishok12:08:28

form-2 without a reaction would work, if you do the @page part inside the render function

antishok12:08:52

also line 14 seems maybe off

shaym12:08:04

here is body-main now , revised

shaym12:08:07

(defn body-main[] (let [page (subscribe [:current-page]) page-function (get pages @page)] (println "page is " @page) (fn [] page-function) ))

antishok12:08:18

that's still not good

antishok12:08:29

@page needs to be done in the (fn [] .. ) part

antishok12:08:06

(that's the render function)

shaym12:08:18

like so :

shaym12:08:19

(defn body-main[] (fn [] (let[[page (subscribe [:current-page]) page-function (get pages @page)]] page-function) )

antishok12:08:21

and it should also probably return [page-function] as was suggested before

antishok12:08:34

the subscribe should not be inside the render function

antishok12:08:42

look at the examples in the re-frame readme :P

shaym12:08:18

so what did you mean by "@page needs to be done in the (fn [] .. ) part "

antishok12:08:41

@page needs to be inside it, subscribe needs to be outside o it

shaym12:08:26

are you referring to the print?

antishok12:08:59

(defn body-main []
 (let [page (subscribe ..)]
  (fn []
    (let [page-function (get pages @page)]
     [page-function]))))

antishok12:08:44

subscribe is outside the fn, @page is inside

shaym12:08:59

i used the above form , if i return a vector i get an arity error , without it i still get partial rndering

antishok12:08:31

does the page-function component take arguments?

antishok12:08:12

oh pages is there, didn't notice

shaym12:08:13

def pages {:project-list [project-table] :project [project-page]}) (defn body-main[] (let [page (subscribe [:current-page]) ] (fn [] (let [page-function (get pages @page)] (println "page is " @page) page-function) ) ))

antishok12:08:27

donno why you're getting an arity error ;S

antishok12:08:54

@shaym: what do you mean by partial rendering?

antishok12:08:47

ohh your pages map already has vectors in it that's why you get the arity error

shaym12:08:53

on first navigation from :project -list to :project , the data from :project is displayed but one button from :project-list is also showing , when i click browser back , and it switches back to :project-list , the table which was originally there is missing

shaym12:08:06

yes pages has a vector

shaym12:08:30

after multiple back and forth navs i get ......Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the same

antishok12:08:15

well not sure what's going on but,

antishok12:08:35

2 things catching my eye are lines 9 and 14 (in your original paste)

shaym12:08:06

what about them?

antishok12:08:16

9 should maybe have [] instead of ()

antishok12:08:22

[entity-table]

antishok12:08:00

and 14 hmm it's wrong because again you're dereffing a subscription outside the render function

antishok12:08:15

not sure what the best approach is to fix it though

antishok12:08:10

what is that subscription pulling out?

antishok12:08:24

(subscribe [:project @project-id])

shaym12:08:48

a specific project from a list, that part actually works simple_smile

shaym12:08:44

i can see the need of returning a function rather then calling a function , but i must admit i am confused as to how many times it needs to be wrapped in a vector , when having a chain of function calls

shaym12:08:27

doesnt it end up [[[[comp]]]] ?

antishok12:08:06

i suppose ;p

shaym12:08:42

so all derefs must be in the render function? i am fixing it now

antishok12:08:50

yes, or in a reaction. i think things can still seem to be working ok even if you do the deref outside, but it will cause the component to be re-rendered on any change to app-db

antishok12:08:00

which you don't want

antishok12:08:05

i might be confusing things though, maybe that's what happens if you do a subscribe inside the render function :P

antishok12:08:37

been a while since i've tested

shaym12:08:07

simple_smile i am confused by now also

shaym12:08:47

i feel like back in my C++ days, pointers to pointers to pointers **my-ptr 😉

antishok12:08:05

ok the 2nd thing i said was correct, as per re-frame readme: Eek! subscription in renderer ... Why is this wrong? Well, this component would be re-rendered every time app-db changed

antishok12:08:34

makes sense, as a subscription means dereffing app-db

shaym12:08:32

i am wondering which is better/easier a chain of functions where the last one returns a vopm , or a chain of componenets nested within each other?

shaym12:08:04

right now it looks like im mixing both

antishok12:08:26

where the last one returns a what?

shaym12:08:22

component , sorry simple_smile

shaym12:08:29

vomp=comp

antishok12:08:54

well a chain of components feels "safer" to me, but i've yet to turn this feeling into an actual explanation i can reason about ;p

shaym12:08:51

i feel the same , but yes it needs to be substantiated

shaym12:08:41

i think it reduced paradigm confusion , all defined the same way

antishok12:08:47

@mikethompson is usually good with putting stuff into words ;)

antishok12:08:25

am sure he'll have some input when he's available

shaym12:08:39

@antishok: thanks for all the help so far