Fork me on GitHub

I had a working app, using re-frame and re-com. I've tried to split it apart, putting reg-event-db, reg-sub, and rendering functions into their own namespaces and now it's stopped working. Inside this app, I have a re-com horizontal-tab component. When I get the on-change event from the horizontal-tab component, I post an event saying that the tab has changed, passing it the value of the new tab. I've confirmed that the function registered via reg-event-db for this event processes this event by updating the database value for it. However, the reg-sub function that this change should trigger doesn't seem to be getting called anymore. Is there some reason why putting the functions in different namespaces would impact things this way? Or do I just have a different bug in my code that I need to look for?


shooting from the hip, but you’re using events like ::thing and when you changed the namespace you’re using ::thing in two different namespaces but that now refers to two different keywords


Yeah, also check your browser's JS console for any warnings from re-frame.


I am using the single-colon form on the event/subscription keywords. I don't have any errors in the JS console.


I tried adding namespace prefixes to all out-of-namespace references, but that did start throwing errors in the JS console. I assumed that meant I was on the wrong track. I've looked at a few examples of real-world re-frame code and breaking things up like this should work fine. Maybe the reg-sub declarations aren't being processed because the compile/load process doesn't execute them? I've required all three new namespaces in my main file, but it's not clear to me whether this code is being compiled into the application. Right now, all I see in the compiled code is the code from my main function. I would assume that I would need to modify my shadow-cljs.edn file to compile/call all of these additional functions.


> Maybe the reg-sub declarations aren't being processed because the compile/load process doesn't execute them? Then re-frame would warn about you trying to use an unregistered sub. Everything that you require should already be compiled-in. If it's a development build, it can easily be in different files that are required via some other means.


Try to create a truly minimal but reproducible example. If you succeed - share it and I'll take a look. But chances are, you'll figure out what's wrong with your code in the process of coming up with such an example.


I'll see if I can do that.


Well, I fixed it, but I'm not sure if it's the right way. Let's say that on the change of tab, one needed to reset the value of a dropdown. Would one reset the dropdown value in the database in the event handler that also changed the tab state, or would one trigger another event that reset the dropdown? It seems that the latter works correctly, but the former has order dependencies on what gets called.


The former should not have any order dependence. Not sure what you mean exactly.


Basically, what I meant was that when I did the following in the event processor:

 (fn [db [_ new-tab-id]]
   (assoc db :selected-tab new-tab-id)
   (assoc db :selected-defn-menu-entry nil)))
only the second change seemed to trigger its subscription function. When I changed the state of the db by adding another change message to the event queue:
 (fn [db [_ new-tab-id]]
   (rf/dispatch [:on-defn-menu-change nil])
   (assoc db :selected-tab new-tab-id)))
both changes happened. I know why the second works correctly - the event is being queued and gets processed after the changes due to the tab switch occurs. What I still don't understand is why the first one seems only to process the second change on the dropdown menu (which is what I meant by order-dependency, albeit not a very good description).


Ah, well. assoc doesn't change db - it creates a completely new value that only references [parts of] the old value. Data structures built into CLJS are immutable for the most part, after all. :) So to make the first event handler work, you gotta do everything in one assoc: (assoc db :x 1 :y 2). Or use -> and thread the same value through multiple forms with assoc or update or what have you.


Gaah! Of course. Thanks for that.

👍 1