Fork me on GitHub

Noob quesiton, why use rf/dispatch to call functions? Why not directly invoke some functions?


I assume you mean something like a not built-in :call-fn effect and not "why use dispatch at all". To simplify views, make their interaction with the outside world more precise (one way to get the data, one way to change it), instrument such calls.


I was referring to the (rf/dispatch [:some-event ]). Why not diretctly call (some-event-func)


Only thing I can come up is the pub/sub functionality. But is there really such a need?


I can't come up with succinct answer to that. I would suggest reading through the documentation at Namely, the main page and the "The Basics" and "Mental Model Omnibus" sections on the left. All while keeping in mind the question: "Would just calling a regular function allow me to do that?"


When you call dispatch, the event is placed in the queue instead of immediately being run - helps with the async singlethreaded nature of js. Far less likely to do bad things in the middle of a render cycle


That particular concern can be easily solved with requestAnimationFrame though.


Aye, trying to write the other things down but words are hard at 2am


And failing miserably to do so, apparently


So a lot of the reasons I’m coming up with are scaling issues


Do you need to do them for a small application? Nah, use functions and swap out an app-state atom


But as things get larger, trying to deal with it becomes far more difficult


Things like decoupling the calling location from the actual implementation


And sidefx are a very useful abstraction


The http-xhrio library is a fantastic example - you trigger a page load, maybe save something to the db to display something for the user, and also do another fx for tracking


These aren’t things that are useful in a small codebase, but it’s a lot easier to keep things separated as you head for that 20KLOC+ codebase


So it seems to me: 1. Async unblocks user actions 2. Decoupling invocation and implementation (good in itself, but using keyword :event-names makes it hard to find the handler, and also hard to refactor had we change the :event-name) 3. pub/sub benefit


Pretty much


Although if you use namespaced event names it makes it very easy to find where things are coming from, usually


I'd say the third one is the main one, even though it is rather ambiguous. Async is easy to handle, as I mentioned. Decoupling is mostly superficial with events - you still have to use the right event name, the right arguments, and call that event at the right time (if the event handler depends on time).


And by default, re-frame queue is only internally async - if you have a bazillion of events, the rendering, along with any user actions, will 100% be blocked. And there are ways around that.


How do you keep track of the event names? While there is a that advises to put event handlers under a dedicated events.cljs file, but I’d prefer a more domain driven model, where I might put the event handlers under account.cljs, sync.cljs, bookmark.cljs, etc. This makes me hard to find out: what event names I’ve defined? Are the being imported on app load or not?


@U24QP2D4J Could you shed some lights on how 20K loc codebase organizes ?


So disclaimer before any of this: this is work done by someone self taught and may/not represent best practice


With that out of the way


There’s a lot of usage of namespaced keywords - almost to the point of abuse sometimes


We’re using pathom, not quite going full fulcro yet but stealing a lot of its ideas


Each table/object has its own resolves.clj for backend resolving, then resolvers.cljs for fetching/storing


Since each fetch really has 2-3 events with it - the fetch itself, the success which marshalls the data into the db, and the failure event (but often the failure is the same event for many)


The mutations similarly have their own, mutations.clj for server side, and mutations.cljs for client side


I’ve seen some people that like to put all their events into a single file to keep them there, but frankly that gets too large too quickly for my taste


Instead, it usually gets broken down by top level key


So all of the above are operating under a specific namespaced key for storing state


There’s another set of namespaces for dealing with app routing - which are also under the same top level keyword


Then other parts of your application which cross multiples of these do so through these singular events. There’s surprisingly few cases where we need to call a ;db that needs to hit multiple top level keywords, but that’s generally solved by factoring out the functions and calling them across


…I have no idea if me describing this makes sense, but hopefully it does?


I am trying to understand it. Is your code publicly available for reference?


You mentioned fulcro. Can I find similar example from fulcro?


No this is work stuff, can’t show it


Not really, I refer to fulcro more in its model of frontend storing objects as reflections of the database ie normalised tables


Each of the resolvers & mutations tables resolve around a table or very small group of tables, their mutation and resolution