Fork me on GitHub
#fulcro
<
2020-07-21
>
dvingo02:07:42

I believe it's a "refresh only transaction". I have this in my notes: This will not mutate any state but trigger the rendering layer to rerender any components that use these fields.

(c/transact! this  [:item/attr-one :item/attr/two])
I can't find it in the book, I think it may have been mentioned in one of the videos

lgessler03:07:20

ok, sounds like something that's de facto deprecated maybe. thanks!

magra12:07:05

Hi, I tried something that seems to work but I would like your opinion whether it is dangerous. I have lists with a few hundred entities where users come back to the same page over and over again. Only about one percent of data changes between page loads. So I tried to load without all the details and put a (when-not details-are-already-loaded (load-field! details {parallel true})) into componentDidMount. That works like a charm when only some of the details need loading and still works like a charm on first load, when 200 or so of these load-fields fire at the same time in parallel. Even on my old Smartphone that seems to work. Fulcro inspect says on all these loads that they are pending. The question is: is this just inspect or am I doing something dangerous? Should I continue to use the parallel load-field! that might fire a few hundred on initial load but garanties smooth sailing afterwards?

dvingo12:07:42

In my experience all parallel loads always show as pending in the inspect tool, no matter the return value.

tony.kay15:07:59

Yeah, that could be a bug in Inspect. Parallel loads should be fine, but understand that the parallel option means it will attempt to push them all down to xhrio immediately, meaning the browsers limit on conncetions will be the “throttle”. You’re now in the land of “will the browser tolerate that?” I don’t see a problem, but who knows 🙂

magra15:07:07

Wow! Thanx! That opens up a new road. I plan to migrate to websockets. That should solve the xhrio limit, right?

tony.kay16:07:22

So websockets “emulate” round trips. So, technically such a parallel request would send them all down the pipe as quickly as possible, and they would all be processed on parallel threads on the server (up to whatever thread pool you had going there). So, yes, websockets will get you around the simultaneous connection limit

tony.kay16:07:02

but then in a multiuser env you might have just created a more interesting server situation

magra16:07:49

Thank you!

magra12:07:08

If this is ok it would open the road for the server to remember a set of all idents a client requested and on mutation check whether the ident in the mutation is in the set-of-idents of a client and if so, send the ident to the client who would mark it :ui/stale so the load-field would know to fire again.

dvingo12:07:42

Could the client send the list of idents on the refresh? that way the server doesn't need to keep track of that.

magra14:07:25

You are right. That way it would be easier to decide what the client is interested in. I think it would depend on the size of this set, too. I think I will start by collecting data on the server to see how much users actually touch in the course of a week an what percentage updates in that time.

tony.kay16:07:39

@zilti new version of rad datomic with your PR is on clojars

tvaughan16:07:52

How do I access url params in a component? I have a component that's a list of things. When some thing in this list is selected (clicked), it's considered selected and some additional data about this thing is then shown in a card elsewhere on the page. I want to be able to represent this in the url. For example, if I wanted to let users pass urls around that would load this list of things and automatically select the thing as specified in the url. Like /teams?selected-team-id=8675309. Or I'd be happy with a route segment like ["teams" :team/id] if there was a way to specify that :team/id is optional or provide a default value. I'm open to all other options. I do have ring's params middleware added and I do know how to work with it, just not within Fulcro. Thanks

tony.kay16:07:13

@tvaughan the translation from a URL to params is always up to you. Route segments are simply a helper for specifying data that (as you noted) will always be present. URL params are in js/window.location. Fulcro dynamic router is simply a ns that provides you with basic features for switching things around on the screen. These are all building blocks. Fulcro intentionally knowns nothing of URLs. It also works in Native land where those don’t exist. Loading is also not a “routing integrated” feature. It makes no sense for a general-purpose library to force you into a corner on when/how to load just for early convenience. So, the short answer is: You interpret your URLs. Period. Dynamic router gives you the ability to show screens according to a basic vector of strings. You figure out a composition for your components that meets your needs…and you need not use what Fulcro provides.

tvaughan17:07:53

Understood. Thanks @U0CKQ19AQ

tony.kay17:07:51

welcome…it’s a lot to navigate

lgessler18:07:00

cursive users: anyone know how to get an action inside a defmutation to indent like an fn? I tried resolving action as fn but the indentation pattern is still wrong

lgessler22:07:01

separately: i find myself often wanting to separate client mutations into two parts: one that concerns only the data model (e.g. setting a value), and one (or more) that concern only the UI (e.g. setting a busy? flag while waiting for a server response). has anyone else made similar divisions? i wonder if maybe i'm overabstracting

tony.kay22:07:29

@lgessler Cursive has built-in support for defmutation, so resolve it as “defmutation” 🙂

🚀 3
tony.kay22:07:08

My general recommendation on mutation bodies is to make helpers and thread it all together so it reads nicely…but that’s about all:

(action [{:keys [state]}]
  (fns/swap!-> state
    (mark-loading)
    (do-other-thing 42)))

tony.kay22:07:02

in terms of full-stack things you can certainly play with making more “sections” by just adopting the current value of default-result-action’s code into your own custom function and setting that as the default mutation action in the app.

tony.kay22:07:56

but that’s just for results…but of course you can use dispatch in action and a custom macro to further pimp it out if you want

lgessler23:07:54

I guess I'm wondering how that works when (do-other-thing 42) needs to be a full-stack mutation, and the return value of that mutation is needed in the UI: in the case i'm dealing with right now, I have a change-password mutation that tells the UI whether or not there was an error and if so what the reason is. this is what the form submission transaction is, in case an example helps: the change-password mutation is run, and in its ok-action it transacts :on-result , and it transacts the :message-handler mutation in case there was an error

(c/transact! this [(mark-busy {:busy? true})
                   (user/change-password
                     {...
                      :on-result        [(mark-busy {:busy? false})]
                      :message-handler  handle-server-message})])

lgessler23:07:08

in this case i don't think i can make change-password a helper fn that just acts on the state atom, right...?

tony.kay23:07:50

but that is why UISM exists…to glue together things that need more glue