Fork me on GitHub
#fulcro
<
2020-02-04
>
tony.kay03:02:13

it’s very old, and was for pre-fulcro (Untangled)…but the concepts are all still what we’re using. Just ignore the Om Next comments.

tony.kay03:02:03

I should really re-do this with nice slides and current API…it would clarify a lot of things for ppl, I think. The “root” is special, but (load! this :some-key SomeClass) loads INTO the root…but the class can be nil if you don’t need normalization…so that can be easily used to load something into the root without needing a dummy class. There is no need to use a join on link queries. [:root-key '_] is perfectly fine, and will pull the entire opaque value (scalar, map, etc.) from the root

🙏 4
👀 4
💯 4
tony.kay03:02:33

i.e. :query [ [:root-key '_] ]

tony.kay03:02:13

Loads always default to the root, and the :target option of load changes that to a diff node in the graph

tony.kay03:02:54

The one complication with link queries is that the client query engine will not flow into a component that has only a link query, but no data of its own. This is explicitly warned about in the book: http://book.fulcrologic.com/#_a_warning_about_ident_and_link_queries

tony.kay03:02:39

For those of you keeping track of RAD: I got some of the validation stuff ironed out today, and cleaned up the generated UI code a bit more. The demo is becoming pretty capable. The coolest thing to come out of all of this cleanup is that defsc-form now just generates a Fulcro component with its own state machine and route that is a “drop in” for regular applications…you can just drop a form into a top-level router (actually subrouter as well if you understand the routing composition). It technically does not require any of the RAD back-end…just Pathom resolvers and an implementation of the save-form mutation (which just sends a form-state diff, which is easy to transform to db writes).

👍 32
4
parrot 4
tony.kay03:02:36

documentation is spotty, but this stuff’s going to be quite useful to anyone writing Fulcro apps, even if they don’t want half of RAD’s services

Jakub HolĂ˝ (HolyJak)16:02:41

@tony.kay I've watched the video but still struggle to understand how to load (parameterized!) data into the root. The use case is: 1. I have the user's ID (from the URL) 2. I want to load his details, ie user-ID => {:id.., :fname..} ; there is only ever a single user so it should be I guess at the root of the tree, eg :global/current-user 3. In my component (under a router, rooted to iff there is a user ID) I want to use the ID and fname So I need something like

`(df/load! SPA
  :global/current-user ; where in the tree root
  [:user/id :user/fname] ; what attributes I want
  {:input [:user/id "id123"]}) ; the inputs Pathom needs`
I don't see how to do that. I'm missing something obvious...

tony.kay16:02:35

@holyjak two ways: 1. create a component with the query you want. and use it in load. or 2. drop the subquery and use nil, but have your resolver for that key just return the full map of what you want.

tony.kay16:02:21

The 3rd option is to use the internal load mutation to write exactly the query you want. That isn’t in the general API because it can easily break normalization.

tony.kay16:02:47

for the case you’re describing, I always do (2)

tony.kay16:02:48

the :input parameter is meaningless. Perhaps you mean :params?

tony.kay16:02:54

(df/load! SPA :global/current-user nil {:params {:input [:user/id 123]}})…but I’m not sure why you’d be saying “current user” and then passing an id of a user…shouldn’t the session on the server figure that out?

tony.kay16:02:40

The load you’re running looks more like it should use: (df/load! SPA [:user/id 123] User {:target :global/current-user})

tony.kay16:02:16

where User is a component with ident/query of a User…which need have no UI

tony.kay16:02:38

but if you’re really trying to do some kind of session thing, then the server should know who the current user is already, and pathom doesn’t need that as input from the client, but it should derive it from the ring request itself (session) (which your middleware can mix into the pathom env)

Jakub HolĂ˝ (HolyJak)17:02:48

Thanks a lot! No, this isn't a session. In reality the user has a secret ID/token (they get a magic url and we extract it from there) we use to fetch some extra data before showing them a list of options and sending them off. What I do currently is as you propose having a User component that is only used for the sake of the query. But it felt hackish... I made up the :input param just for the purpose of demonstration. I assume ld that :params could possibly be used for that but could find the docs explaining them in detail. I'm sure they are out there somewhere in the book or docstrings... If I go with (2) then I need to write a resolver for :global/current-user returning the user map and getting the ID from its env, right? If I send {:params {:myid 123}} then I find it somewhere inside the defresolver's env param, right?

tony.kay19:02:36

@holyjak the params are in the top-level resolver (the first one hit), but you can easily make a pathom plugin that pulls it into the env (see the RAD code, which does that) https://github.com/fulcrologic/fulcro-rad/blob/develop/src/main/com/fulcrologic/rad/pathom.clj#L135. If you use the ident-based query, then it will trigger the resolver for that ident (i.e. :user/id) and you won’t need a param. Using a component for queries is not a hack. It’s a well-supported pattern for loading data that has no direct UI.

👍 4
Jakub HolĂ˝ (HolyJak)21:02:02

Ok, thank you so much! I feeled as a hack because I see componens primarily as "(visual) things in the UI". I have yet to learn to see it the Fulcro way :) I'll go with the ident query if that is an accepted and also it seems simplest way. Thank you!!!

tony.kay22:02:18

I’ve thought about making a defquery macro, but it would just be an alias to defsc basically…seems pointless

✅ 4
tony.kay22:02:28

other than to give ppl the warm fuzzies 😜

tony.kay22:02:37

which is a consideration

tony.kay22:02:59

but the book does advertise it as an acceptable use-case.

Jakub HolĂ˝ (HolyJak)09:02:56

I had the same thought, that it would be pointless. I have read big chunks of the book but not all - and am already forgetting what I read before 😱

tony.kay15:02:31

yeah, understood.

tony.kay19:02:29

normally the query params are only in the entry-point’s AST, since that is how they are sent

thomas20:02:49

Hi, I have a df/load! ...{ options... } and in the map of options I have a :post-action My colleagues weren't sure if that is the right thing to do though as it isn't in the docs.

daniel.spaniel22:02:58

What is the hook to call on a component when you render it. For example on

defsc-route-target
there is the componentDidMount hook but I on plain defsc what hook is equivalent to that one .. i have tried a few like
:componentDidUpdate

daniel.spaniel22:02:02

but did not do anything

tony.kay22:02:26

@dansudol all of the normal react lifecycle methods work. See docstring of defsc

tony.kay22:02:48

:componentDidUpdate works

tony.kay22:02:02

be sure to reload your app…that change will not take effect on mounted components

tony.kay22:02:40

@thomas It isn’t in the docstring?

tony.kay22:02:10

looks like it is in the docs to me

tony.kay22:02:28

The book cannot possibly be kept up to date to be exhaustive

tony.kay22:02:45

I’m more likely to update docstrings on API additions

tony.kay22:02:53

it’s sort of a shortcut when you feel that a post mutation is overkill…I generally don’t use it, but it was trivial to provide

tony.kay22:02:35

See also ok-action and error-action params, which are similar

daniel.spaniel22:02:54

thanks @tony.kay I was checking the docstring and I saw the :componentDidUpdate there. For some reason it does not run when I render the component .. but I will try again .. or load stuff before render ..

tony.kay22:02:19

React lifecycle docs….that one does NOT run on mount

tony.kay22:02:27

only on UPDATE

tony.kay22:02:11

first sentence of the docs

tony.kay22:02:31

please remember that Fulcro is not responsible for implementing lifecycles…use React docs

daniel.spaniel22:02:15

gotcha .. i understand .. and good pointer to that react doc .. got it 🙂