Fork me on GitHub
#fulcro
<
2020-02-03
>
pithyless08:02:13

https://github.com/fulcrologic/fulcro-rad-datomic/blob/develop/src/main/com/fulcrologic/rad/database_adapters/datomic.clj#L98-L100 I'm studying the fulcro-rad codebase. Can someone shed some light on this bit of code? AFAICT, the then-branch is noop, because ref->ident will never be true for nil. Is it an oversight or am I missing something?

davewo15:02:55

probably an oversight :-)

currentoor17:02:38

that code was ported by @U0CKQ19AQ from code i wrote in our SaaS product, ref->ident in the version i wrote had a different definition

currentoor17:02:42

(defn ref->ident
  "Sometimes references on the client are actual idents and sometimes they are
  nested maps, this function attempts to return an ident regardless."
  [x]
  (cond
    (eql/ident? x) x
    (map? x) (some #(and (or (#{:payment-processor/title} (first %))
                           (#{"id" "upc"} (name (first %))))
                      (into [] %)) x)
    :else nil))

currentoor17:02:25

i’m not sure why he changed it, but RAD is still a WIP

tony.kay18:02:52

look at your code…the original was tied to a specific special case in schema

tony.kay18:02:59

which simplifies to the version I wrote

tony.kay18:02:46

and you are correct @U05476190, the if within that was handling a special case in the original

tony.kay18:02:10

Porting working code: I just did not analyze the result for dead code

pithyless18:02:01

cool, this was just an FYI for you @U0CKQ19AQ - that entire first cond condition seems unnecessary, I think all cases are covered elsewhere

tony.kay18:02:53

yeah, there is more reworking to do…the whole thing needs a layer for security checking and general validation…probably not here, but this is all still general design, so I’m not being too picking about cleaning up yet

otwieracz09:02:57

Is there any "special" approach to forms in Fulcro? Or should I just create react-bootstrap form (in my case) and handle "send" button with mutation?

Robin Jakobsson09:02:38

@UB0EMUD34 it depends on your specific requirements. If you like the features that comes with Fulcro Form State (http://book.fulcrologic.com/#FormState), go with it.

👍 4
tony.kay02:02:05

I strongly recommend making a UI state machine and using Form State support. You can generalize the vast majority of your forms this way…which is what I’m doing in RAD.

tony.kay02:02:39

As RAD matures, you mostly won’t have to write much of any logic to make forms (or UI if you do not want to).

Jakub Holý (HolyJak)10:02:46

Hello! I struggle to write a query to fetch a root entity from the database (to be set on a component somewhere in the UI tree). This is in my DB:

{:global/offboarding [:offboarding/id "offbid123"],
 :offboarding/id {"offbid123" {:offboarding/id "offbid123", :offboarding/dummy? true}}}
I read about http://book.fulcrologic.com/#_link_queries and assumed that it's what I need here. But the following: query (run in Fulcro Inspect - Query) fails to return the data:
[{[:global/offboarding '_] [:offboarding/id :offboarding/dummy?]}] 
; => {[:global/offboarding '_] {:offboarding/id :com.wsscode.pathom.core/not-found, :offboarding/dummy? :com.wsscode.pathom.core/not-found}}
Any tips? Thank you!!! I have also tried to run this without the link query syntax, assuming that Query runs against the root of the graph, but that returns nothing as well: [{:global/offboarding [:offboarding/id :offboarding/dummy?]}] ; => {:global/offboarding {}} .

Jakub Holý (HolyJak)11:02:31

I have tried to replicate http://book.fulcrologic.com/#_link_queries but without success: I have inserted the root level item with

(merge/merge! SPA {:ui/locale "EN"} [:ui/locale])
and queried it using the query from the book, inside the Fulcro Inspect > Query:
[ [:ui/locale '_]]
; => {[:ui/locale '_]
;     {:ui/fetch-state {:fulcro.client.impl.data-fetch/type :not-found}}}
BTW, is there a function I can use to execute a query? Something that would take the app and a component or a query and return the data tree? I couldn't find anything.

pithyless13:02:14

Fulcro Inspect > Query is for queries to your server

pithyless13:02:39

You need to use the db->tree mechanism and use a component get-query (which will add metadata about idents and queries), otherwise Fulcro won't understand the joins

👍 4
Jakub Holý (HolyJak)15:02:10

Ah, thank you! I assumed I could run component queries against the client DB in Query. That explains it. And thank you for the pointer to db->tree! I remember I saw it mentioned but somehow haven't remember it when looking for how to "execute" a query...

Jakub Holý (HolyJak)16:02:10

Is this the correct way?

(com.fulcrologic.fulcro.algorithms.denormalize/db->tree
    (comp/get-query Root)
    (
app/current-state app.application/SPA
)
    (app/current-state app.application/SPA))
(I would never find out the right way to call it without the examples in the book)

4
jorda0mega16:02:06

by any chance are there any courses/video streams teaching fulcro by implementing a simple app (something similar to https://www.jacekschae.com/learn-re-frame-pro)?

davewo16:02:58

@jorda0mega nothing I know of that is structured in this way. The Fulcro tutorials on youtube are very well done, and hit all the concepts needed for even non-simple apps 🙂 https://www.youtube.com/playlist?list=PLVi9lDx-4C_T7jkihlQflyqGqU4xVtsfi

👍 4
jorda0mega16:02:36

these are indeed great. I was looking more for a course that someone new to clojure could follow step by step to get an app running - to avoid the feeling of being overwhelmed by so many new concepts :(

davewo17:02:49

ah, if you are brand-new to clojure (welcome!!) you might want to check out https://www.braveclojure.com/foreword/ ...there is quite a bit of prerequisite knowledge that is assumed coming into those videos. Also assumed is a working knowledge of React.

davewo16:02:04

We could probably talk Tony into putting the tutorials behind a paywall, if that would help 😂

4
Jakub Holý (HolyJak)21:02:00

Hello! I have a weird problem where running a client-side query manually yields the expected results but the component with the query only ever has empty props. I guess 1 possible explanation would be if somehow the component was rendered before the data was loaded and not re-rendered thereafter. (Can I, BTW, force a component to re-render?) The query:

(let [state (app/current-state app.application/SPA)]
    (denormalize/db->tree
      (comp/get-query OffboardingPages)
      state state))
;; => {:global/offboarding {:offboarding/id "offbid123", :offboarding/dummy? true}}
The component that gets {} props, a child of a router:
(defsc OffboardingPages [_ {{:offboarding/keys [id dummy?]} :global/offboarding :as props}]
  {:query         [{[:global/offboarding '_] [:offboarding/id :offboarding/dummy?]}]
   :ident         (fn [] [:component/id :offboarding-pages])
   :initial-state {:global/offboarding {}}
   :route-segment [:offboarding-id]
   :will-enter    (fn [app {:keys [offboarding-id]}]
                    (dr/route-deferred
                      [:component/id :offboarding-pages]
                      #(df/load! app [:offboarding/id offboarding-id] OffboardingPages
                                 {:post-mutation        `dr/target-ready
                                  :post-mutation-params {:target [:component/id :offboarding-pages]}
                                  :target               [:global/offboarding]})))}
  (println "OffboardingPages props:" props)
  (div
    (p (str "TMP: Info for offboarding id='" id "'; dummy? " dummy?))))
;; prints: OffboardingPages props: {}
What do I do wrong? How can I fix it? Thank you! I am at a loss 😞

4
Jakub Holý (HolyJak)21:02:41

I still don't have a solution but I know the cause - the code and app state were out of sync since after I changed the query from the simple [:offboarding/id :offboarding/dummy?] to the current one, which has broken the query to the server and thus loading 😞

tony.kay03:02:40

1. You cannot use :initial-state to initialize something at the root from some sub-component. Initial state is composed together as a tree from root. See book. 2. You Root component’s :initial-state must include something for :global/offboarding 3. The initial state for this component must stll be present (even if it is an empty map), because otherwise the query will not be run (there won’t be a link to the entity of the component, so the query engine won’t bother). 4. :route-segment should not be only a parameter, otherwise it will match all routes (since anything can match). You should always have a prefix string in there.

👍 4
tony.kay03:02:24

Also, it matters how you compose a child into a parent…so giving a localized component like this does not expose all possible problems, since we cannot see the immediate parent. In this case I’m assuming a router, which should be fine.

4
Jakub Holý (HolyJak)09:02:34

Thanks a lot! I will look into this... Regarding 4. :route-segment - in my cases I only care about two cases: there is a parameter (offboarding ID) or the parameter is missing so it seems still to work. (I do it this way to keep the same URLs as the production version of the app that I am rewriting in Fulcro). I actually have this in may router:

:router-targets 
[ #_1 LoadingIndicator
 #_2 HomeMissingOffboardingId
 #_3 OffboardingPages]
1. Shows automatically while waiting for the deferred 3. (I expected the router's own body to show while loading but it only shows briefly between 1. and 3. Segment = ["loading"] - but we never explicitly route to it 2. Shows if there is no offboarding ID in the url <> route thanks to segment=`[""]` 3. Shows when there is a param in the URL (deferred, after it finished loading the data) Is it too hackish?

Jakub Holý (HolyJak)21:02:41

How to load a thing that has an ID but that there is always only one for the given user and use it? I tried ☝️ but that doesn't work; I would need to load! not the component's query (with the link query to the root) but simple [:offboarding/id :offboarding/dummy?]`` I feel I'm doing it wrong... I guess I need to split the OffboardingPages component in two, with an extra parent component with the query [{[:global/offboarding '_] (comp/get-query OffboardingPages)}] Do I need a dummy component like this just to be able to split the query to work?!