Fork me on GitHub
#fulcro
<
2020-02-07
>
Jakub Holý (HolyJak)17:02:39

I am trying to understand how routing params are/can be used to decide what data end up in the target component's props. Imagine I have the component tree Root -> Router -> Person and want to show a particular person based on the URL. (Ignoring the URL <-> route part here.) So "/person/1" should show [:person/id 1] and I do have :route-segment ["person" :id] on Person and (if I need it?) :will-enter (fn [app {:keys [id]}] (dr/route-immediate [:person/id id])). But I do not see how should this work. (1) When/how can the Person's query [:person/id :person/name :person/age] be turned into something resolvable against the DB, i.e. [{[:person/id 1] [...]}]? (2) And how is data passed from Root to Person? Router has :alt0 (get-query Person) in its query but when this is resolved against the DB, there is no :alt0 top-level element. I'd assume that somehow the target's query is resolved against the Router's parent's props (in this case, the DB itself). How does this work?! (Bonus question: (3) Is this a totally wrong approach? Should I just use (nth people id-from-url) in Root?) Thank you!!!

thosmos17:02:28

I do something similar, but I transact a new record into that ident before calling route-immediate …

:will-enter            (fn [app {:keys [sv-id] :as params}]
                            (let [is-new?      (= sv-id "new")
                                  sv-id        (if is-new?
                                                 (make-tempid)
                                                 sv-id)
                                  sv-ident     [:org.riverdb.db.sitevisit/gid sv-id]
                                  editor-ident [:component/id :sitevisit-editor]]
                              (log/debug "WILL ENTER" sv-id "NEW?" is-new? "PARAMS" params)
                              (when is-new?
                                (comp/transact! app `[(merge-new-sv ~{:sv-ident sv-ident})]))
                              (if is-new?
                                (dr/route-immediate editor-ident)
                                (dr/route-deferred editor-ident
                                  #(f/load! app sv-ident SiteVisitForm ...
so my URL is “/sitevisit/edit/new” for a new one, or “sitevisit/edit/12345" for an existing one

thosmos17:02:30

the down side is that :will-enter runs 3 times so I’m creating 3 temp entities in state every time. I haven’t figured out yet a better strategy … maybe do a route-deferred and create the temp-id in the handler fn

Jakub Holý (HolyJak)17:02:25

I see that you do ± the same thing as me but I still don't understand how is the information [:org.riverdb.db.sitevisit/gid sv-id] combined with the component's query to make a query that can be resolved against the DB....

thosmos17:02:37

The router reads the component’s query and then uses that to read the ident location

thosmos17:02:49

is that what you mean?

thosmos17:02:28

the router changes its own query tree based on which component is currently active by reading the component’s query and then updating its own query tree with that new branch, and removing the branch of the old path

thosmos17:02:38

so you just need to make sure that data exists in the DB at that ident that fulfills the component’s query, and it will work

Jakub Holý (HolyJak)17:02:03

So the router changes its own query (in your case) to ...{[:org.riverdb.db.sitevisit/gid 123] (get-query current-target-lcass)}... ? I do not see that. What I see is

{::current-route `(comp/get-query ~(first router-targets))}
(map-indexed ... {(keyword (str "alt" idx)) `(comp/get-query ~s)}
but that does not work with the ident at all...

Jakub Holý (HolyJak)17:02:16

Another question: How to view a Fulcro component's props? The React Dev Tools Components view shows the useless: fulcro$value: (undefined) { {__hash: null, cljs$lang$protocol_mask$partition0$:…}, ...} and Fulcro Inspector does not have its own Components tree view...

cjmurphy17:02:02

App State is organised by ident so use Fulcro Inspect and think in terms of idents. There might be several components in one ident family.

Jakub Holý (HolyJak)18:02:06

Hm, I have PersonList with :ident :list/id and in the DB there is :list/id {0: .., 1: ..}which is the data from the initial state . But what props does the PersonList displayed on the page have?

cjmurphy18:02:33

The displayed one will be one of the ids (or many of them if it is a component that displays many). Each 'row' will have data determined by the query on the component.

Jakub Holý (HolyJak)18:02:03

In theory yes. But in practice the list is showing empty, so it is missing some props. That's why I would like to see the props it got - but don't how to. Perhaps the only solution is to add (println props) to its code...

cjmurphy18:02:02

Yes - but doing so will just be verifying that you don't have a rendering problem. Are you saying each row only has :list/id and there should also be :list/name etc.?

Jakub Holý (HolyJak)18:02:13

Which row??? The DB contains the data it should. But my component has an empty body. So there is something wrong in the transitions of values from the client db into the component (which I have put under a router, see my previous question, though there I mention Person not PersonList)

cjmurphy18:02:11

The id (of the ident, the second thing in it) gives the row, you can print it from the component rendering function.

cjmurphy18:02:15

There shouldn't be rendering problems if you use:

:optimized-render! keyframe-renderer2/render!

cjmurphy18:02:05

(or keyframe-renderer for that matter).

cjmurphy18:02:53

For printing purposes de-structure the id from the props.

thosmos20:02:10

In Inspect are the props in the list’s parent? If so, then they’re not getting passed to the list component. You can proceed in this manner through the tree to your component.