re-frame

Linus Ericsson 2025-10-30T13:35:27.602679Z

In https://day8.github.io/re-frame/Subscribing-To-External-Data/#via-a-subscription there is an example where a component can subscribe to a subscription handler and that subscription handler loads data from an external source when the subscription is initialized. This is very nice. I have a situation where I need to load data in two (or more) steps since the steps are dependent on each other, is this possible to solve in a similar way? Ie the component says what it needs, the subscription handler realizes this needs to be solved with several sub requests, and these requests could be done in a dependency order? Maybe the flow functionality? The subscriptions and the locally stored data should be disposed in a reasonable order as well.

p-himik 2025-10-30T13:40:54.125339Z

FWIW I really, really don't like that approach. It might look and feel clean, but it defeats the whole purpose of re-frame, I'm not even exaggerating here. The view becomes the driver of your app, not the data. > I need to load data in two (or more) steps since the steps are dependent on each other, is this possible to solve in a similar way? Yes, since the example uses plain dispatch. You can dispatch an event that dispatches other events via the :dispatch effect. It can be an arbitrary graph of events.

Linus Ericsson 2025-10-30T13:56:57.841139Z

I agree that there are problems with this approach. But then what is a good approach to complex loading of data in re-frame? The navigation states which "top view" that should be seen, so the view at least in principle dictates which data is needed for the moment. During the life cycle of loading (and storing) data the view must have a decent chance to represent the state (which could be driven either by the subscription handler + some presentation logic or something else). Currently we have a different machinery that starts loading and unloading data depending on what is defined by the route definition the navigation sees, (which IMO is quite similar to which top node is shown). Component life cycles are maybe not the best place to hint for data loaders, either. A radically different example, Fulcro, can extract the query information needed from the components it will want to show (but leaves the implementation of data fetching up to the programmer). This at least gives very specific hooks on where the data fetching etc could be performed. A data fetching framework for re-frame could be able to do something similar by looking at a subset of which subscriptions that are created, no?

Linus Ericsson 2025-10-30T14:14:07.966439Z

I know this kind of loading of data is a surprisingly complex problem for any framework, but since the documentation suggested this solution I want to understand if it actually scales in practice.

p-himik 2025-10-30T14:19:06.799619Z

> But then what is a good approach to complex loading of data in re-frame? I can't describe something that's guaranteed to work every time, but I myself have always been able to structure my apps in a way where global interceptors allowed me to tackle this perfectly, and I'd say the code became better with that approach. But there could be instances where it's not feasible - I might have blind spots I'm not aware about. > The navigation states which "top view" that should be seen, so the view at least in principle dictates which data is needed for the moment. > [...] > Currently we have a different machinery that starts loading and unloading data depending on what is defined by the route definition the navigation sees, (which IMO is quite similar to which top node is shown). The "top view" in my apps is always dictated by the URL, yes. And all preparation and clean up happens upon navigation. All nested views that need something that isn't part of the top-level machinery provide their own events. Those events could be triggered by global interceptors or by parent views.

👍 1
Kimo 2025-10-30T14:20:22.707779Z

I've had good experience using https://day8.github.io/re-frame/Flows/ as well - as an alternative to global interceptors.

👍 1
lassemaatta 2025-10-30T15:18:33.408749Z

@p-himik, could you expand upon your approach on using global interceptors? I haven't used them and it isn't immediately obvious to me how they help in this situation

p-himik 2025-10-30T15:53:30.342439Z

In this day and age, it's probably better to use flows. :) It's just that I haven't hand any new projects since their introduction so I haven't used them yet. But anything flows can do, global interceptors can also do, just with more ceremony.

👍 1
p-himik 2025-10-30T16:00:08.191239Z

But in general, whatever you have on screen is a function of app-db, apart from some transient things like maybe some animations or tooltips. So when you change some app-db state to show some particular view, the namespace that defines that view could also define a flow or a global interceptor that, when the data making that particular view show up becomes available, also triggers something else.

p-himik 2025-10-30T16:01:50.102729Z

Of course, the vast majority of such things end up in a single event like ::show-view. It both sets up the necessary immediate state, sets up some process to get more data, and then, via other "child" events tears the process down and writes the data. It can also track whether the current state has changed before the data has arrived, there are various libraries for that as well.

lassemaatta 2025-10-30T16:05:06.333759Z

yeah, I sometimes find myself lost in a tree of subscriptions where N levels deep I finally have a value that indicates I need to fetch some additional data from the backend and I have no way to communicate that. I suppose flows help with this as the logic can be moved there.

p-himik 2025-10-30T16:10:43.994769Z

Hard to say without seeing the actual code, of course. But even if some subscriptions is 15 layers deep, something that changes the data in app-db that leads to a view changing in a way that requires some async process is still caused by a top-level event. "Top level" in the sense that the event can be considered in isolation, it's a subject to global interceptors just like any other event.

lassemaatta 2025-10-30T16:11:42.175059Z

sure, of course