Fork me on GitHub

Technically, global error action is called within tx processing, and you’re guaranteed a render after it finishes processing things. This means you could directly swap against the state atom in the global-error-action instead of having to write a mutation (


There’s no real benefit to using a mutation there, since you’re really augmenting internal logic, and you don’t plan on doing any full-stack operation, nor do you need a CQRS history of what you did in response to a full-stack error.

👍 3

In you might consider looking at default-result-action for mutations. Mutations have ref in env (which is the ident of the component that ran the mutation). There is a built-in variant of what you’re talking about here, but I think I’ve forgotten to document it:


It could be that I forgot to finish the feature 😊


but you see that will make sure the data is placed in app state on the component independent of the query. I think perhaps this feature isn’t finished, since it should probably use a :ui prop so that you can add it to the query and have it “just work”. Perhaps play with it.


it can be easily overridden, and as you mention in your article you can prevent it on the network query using global eql transform.


Another thing to note: The pathom path stuff is nice, but consider this idea: Make sure resolvers never throw, and have them return errors as first-class data. Remember my points here: Summary: only (detectable) security hacks and (unexpected) bugs should be hard-core errors. Intentional behavior of your server should always return a sensical value for a query, which may in fact simply be something like: “form save failed”. In that case components can query for problems with a real query prop, and each resolver can populate that key with an error if it has one.


So, if you want to do component-level error handling, just adopt that philosophy and make remote-error? assume that something serious went wrong and the user probably should call support, reload the page, and perhaps even log back in.

Jakub Holý (HolyJak)16:07:18

Thanks a lot for the feedback!!! > Make sure resolvers never throw, and have them return errors as first-class data. That would be ideal but requires me to wrap each in try-catch or add a pathom transform - and if I forget somewhere and it fails, I'm screwed. The errors I'm getting are mostly unexpected (bug, downstream service issues,..)


right, but then that’s a bug 🙂


or you can define your own defresolver macro that does it for you (which is what I do, but I also add some addl security logic in as well)

👍 3
Jakub Holý (HolyJak)16:07:04

I encounter mostly bugs and downstream service issues. This is an internal app so I don't worry about exposing the tech error details to the users and it makes troubleshooting easier and little les bad UX :)


@jatkin wondering how your “reducers” and “subscriptions” for Fulcro are coming along. Interested in seeing what you’ve come up with.


Wrapped it up last night actually. Will send more info when I get to my computer :)


This does not have many details on the readme, but the code is short-ish. Maybe it's better to see the workspaces first.


Basically the model is every subscription is a function, and the interesting part of the api is how to create that function by chaining dependencies, keeping it efficient with short-circuit signals, (coming soon) memoization, (coming soon) push first models that don't call every function on render. Currently this works fine for my usecase though - I will have at most 15-20 subscriptions active on a screen.


On dynamic routers - why do I need to run this

(comp/get-query (comp/factory Component {:qualifier component-id}))
to get the current query? What is :qualifier doing in here?


dynamic queries, by default, are tied to the class. The qualifier on a factory lets you have different queries for different instances in the UI


so, that allows each on-screen instance of Component to have a customer query based on the ID of the component


dynamic queries in older versions used component-local state, which made it “easier”, but also made a lot of different features unworkable, such as dynamic queries in CLJ, re-starting an app purely from state, etc, etc.


Cool. Makes sense.


Is it possible to set dynamic queries on a per-component-instance level? Basically union queries but without the nesting.


Make a class per component or use qualifiers. Those are your options


Right. Saw that. The problem is that I have an unknown number of possibilities that I’d like to configure at runtime. If I’m not misunderstanding i need to set this up at compile time.


you can generate factories on the fly


the code you quoted to me earlier does just that


so I’m confused as to what is missing for your use-case


OO. I thought it was because routers were singletons that worked. (Found that in the old router)


I tried running it at the repl and was hitting roadblocks. I’ll revisit and see if I was just being stupid.


What could be the reasons when a defsc with a route loads its content fine when accessed directly (going directly to that URL or refreshing the browser), but when routed to "normally" it fails?


are the loads you need for that route happening in both cases?

Jakub Holý (HolyJak)07:07:45

Could you define "fail"? And is this a deferred route? Does the state of the parent component of the router contain the router state in both cases?


It is a deferred route, yes, the page loads fine, but the data to be displayed in the table is missing.


The loading is done with fd/load! in :will-enter


...well, now I broke it completely... sigh