Fork me on GitHub
#fulcro
<
2021-08-12
>
genekim15:08:41

@tony.kay I’ve noticed that you use function names that end with * like this — do I understand correctly that these indicate that the function mutate the Fulcro state atom? (And PS: I really like how succinct these functions are… the ones I’ve written are much more verbose, but less clear.)

(defn add-row-to-report* [state-map rad-report-id row-ident]
  (update-in state-map [::report/id rad-report-id :ui/loaded-data] conj row-ident))

Tyler Nisonoff16:08:01

its a function that mutates the state map (as opposed to passing in the atom and then deref-ing it). Tony discusses it in the book https://book.fulcrologic.com/#_mutation_helpers

genekim20:08:53

Nice. Thx!!!

tony.kay20:08:26

There's a not-very-visible helper that I don't think I mention in the book: c.f.f.a.normalized-state/swap!-> that makes them a small bit prettier:

(swap!-> state
  (add-row-report* report-id ident)
  ...)
basically, it eliminates the need for a (fn [s]) wrapper when composing these.

👍 3
sheluchin17:08:22

When using a DB like Crux with Fulcro, is it best to use maps for the :crux.db/ids? So in the case of a user with ident [:user/id 1] the :crux.db/id would be {:user/id 1}? Seems like this option is most consistent with the Fulcro/Pathom conventions. https://opencrux.com/reference/transactions.html#valid-ids

tony.kay20:08:03

So, you can always resolve something into a ns. In native mode for Datomic we just map :db/id into the right thing...for example:

(defresolver all-people [env input]
  {::pc/output {:people/ALL [:person/id]}}
  (let [crux-things ...query...]
     {:people/ALL (mapv #(assoc % :person/id (:crux.db/id %)) crux-things)}))

(defresolver person-resolver [env {:person/keys [id]}]
   ...query where `id` is used as a crux id...)
The end user has no idea that crux IDs are in use. Of course, this means that you can hand the wrong kind of ID to a resolver and get something else...so a bit of error checking is nice.

tony.kay20:08:36

Same thing for writes...they supply a :person/id, and you put it in crux id

tony.kay20:08:11

But if you want to play with a map-as-an-id concept, it should not break anything. I do that in form-state, I think.

sheluchin21:08:39

So then what kind of values make sense for :crux.db/id? Always use UUIDs? Because if integers are used for ids then they won't be unique across different types of entities. Or am I following what you're explaining correctly? Sounds like you're suggesting to just use globally unique ids for all entities and use the same value in both :crux.db/id and :some-entity/id.

tony.kay22:08:28

What you use as the IDs value is irrelevant to Pathom/Fulcro. If Crux needs it to be globally unique, then yes, seems like a UUID will fit the bill. Check with them on indexing to see if you should use squuids

👍 3
lgessler05:08:49

the solution I used is to assoc the same uuid in at both :crux.db/id and :foo/id--you don't need to worry about :crux.db/id being there since pathom won't let it out anyway since it's not in outputs, and you don't need to do any extra work to make pathom/fulcro happy

👍 3
lgessler05:08:22

I actually like your idea to have :crux.db/id be the map, though, because I think that means you can have joins in other entities not require any special handling? With the way I do it, a join to foo looks like {:bar/foo-join #uuid ...} and I need to do some extra work to make that look like {:bar/foo-join {:foo/id #uuid ...}}

👍 6
lgessler05:08:48

but if the crux.db/id is already {:foo/id #uuid ...} you don't have to worry about tweaking joins like that

tvaughan17:08:26

When using server-side rendering with a given route, how should I produce the "rendered state" of the component that matches the route? I know how to get the target, e.g. (route-target SomeRouterComponent some-uri), and I know how to get the initial state of this target, e.g. (get-initial-state (:target result-of-route-target)), but how can I trigger side-effects, e.g. those in :will-enter, so I can insert a complete data map of this component into the server-side state map? I have to do something similar with a session component. I'm calling a pathom endpoint, then inserting the session into the server-side state map using get-ident on the session data returned by the pathom endpoint. Is this what I should be doing to build the state of the route target? I couldn't get route-to* to work either, though I didn't try very hard as I'm not sure this is the correct approach either. Thanks

tony.kay20:08:06

If you're going full-meal-deal with SSR you probably need to start a fulcro app on the server (no need to mount it), and install a CLJ remote that just calls your server-side parser directly. Component lifecycle stuff won't fire, but if your code is CLJC then DR should trigger its various events. Of course, then you have to do something to know when the whole mess is done. DR can't detect the current visible route on an unmounted app (I have functions written to do that but have not pushed them back into DR), but SM stuff should still happen.

tvaughan20:08:43

> If you're going full-meal-deal with SSR you probably need to start a fulcro app on the server (no need to mount it) Yes, we are. Or rather that's our goal. > and install a CLJ remote that just calls your server-side parser directly. OK. Thanks. > if your code is CLJC Yes, it is. > then DR should trigger its various events. Of course, then you have to do something to know when the whole mess is done. DR can't detect the current visible route on an unmounted app OK. Good to know. Thanks @tony.kay

tony.kay20:08:43

https://gist.github.com/awkay/1d8f7e24ba5cf52a5ad20f9852e6cf7a might come in handy, since most of them work without React/active mount.

🎉 2
tvaughan14:08:27

Hey @U0522TWDA. Thanks, yes I have seen that. You helped me come up with this. What I have is https://gist.github.com/carrete/57979732b1c57970596f72c888fbf04d. I think the issue is on line 11 (of my gist) where we only get the initial state of the target component. What I need is the complete component state. For example, a request for /document/1 corresponds to the DocumentView component (which is routable, e.g. includes a route target and initial state) and should cause a query to the backend for the data associated with document 1. The backend returns the document id which is used in the component as its id, i.e. :ident :document/id. What's happening now with server-side rendering is that the initial state of the target lacks a document id which means the initial state of the target is inserted with a :document/id of nil because no query is being made to the backend. Does this make sense? Thanks again!

Jakub Holý (HolyJak)15:08:05

Do what Tony suggested - create a server-side fulcro-app with a "fake" remote that simply calls your Pathom parser directly and initialize it similarly as you do in client.cljs (but without mounting). Then you can do (dr/change-route! app ["landing-page"]) or similar to get the correct view for the request. (This might be asynchronous somewhat so we'd need to figure out how to handle that, i.e. how to wait until the app is done routing.)

tvaughan15:08:19

Cool. Thanks for the clarification

Jakub Holý (HolyJak)15:08:46

Good luck! Please share your progress 🙂

tvaughan15:08:03

I will indeed!

❤️ 3