On EP 002 - Multiple re-frame Instances <- overload subscribe/dispatch to accept a r/atom to use in place of app-db #741
dannyfreeman
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
An idea I've been pondering
I've been really itching for something like EP 002. So much so that for my job we are experimenting with alternative implementations of
reg-sub
,reg-event-*
,subscribe
, anddispatch
that could operate on ratoms other than app-db. The idea would be to have a component create a ratom (ordefonce
it somewhere), and pass that ratom through to it's child components. Overloaded versions ofdispatch
andsubscribe
would accept an optional ratom that would be used in events and subscriptions. It might be used something like this:The end goal is that we can have complex re-usable components that can exist in multiple places on a single page. And things like devcards. Those components could be written with the re-frame semantics of subs and events we know and love. And we know they won't stomp on each other's app-db state.
While working on this implementation in a separate library I came to the realization that it would be easier to implement that by forking re-frame, so I did just that.
POC For the Idea
It turned out to be relatively simple after trying to hack around it outside of the re-frame code for a couple days. Here is a link to the branch on my fork:
dannyfreeman/re-frame@master...dannyfreeman:multiple-app-dbs
That has the overloaded
subscribe
anddispatch
variants. I had to add a new type offx
calledframe-fx
that provides the current ratom (I am calling this ratom aframe
in the code, because I've seen the name thrown around in discussions here) in order to make:db
:dispatch
and similar effects work on the current frame. I also added some new fx like:app-db/dispatch
that always dispatch to the global app-db, event if the current event is operating on a different frame. I've found something like that to be necessary if you pass an event vector into a component that operates on a separate frame, but needs to dispatch out of the frame back into your app's global state when something important happens.All but one test passed when I made these changes, and that test failed because I modified the subscription cache key to also include the
reagent-id
of whatever frame the subscription ran on. Everything else seems to be working without any breaking changes that I can find, but I'm sure there are things I've overlooked.Example Usage
I re-worked the todo-mvc example to flex the new code a little bit, which can be seen on this branch working off my
multipel-app-dbs
branch : dannyfreeman/re-frame@multiple-app-dbs...todomvc-with-frames. The todo app makes use of a new namespace I added:re-frame.frame
. The new namespace has some helper functions and react-hooks that allow for a frame to be created in a high-up-the-dom component somewhere and then accessed via ause-frame
hook anywhere in the component hierarchy underneath without needing to pass it as an argument to each component. It needs functional components enabled in reagent to work unfortunately, but I've yet to find other solutions outside what I consider to be pretty nasty interop with react's old context consumer api (which should work in this case if it's wanted). When functional components can't be used I personally don't mind passing a frame around as an argument to other components. Especially since that frame can also hold onto any props and swap! them in as they change.I was pretty successful with that and in running a very large re-frame app at my job against this branch without breaking anything. I am wondering what the maintainers think of this idea and if it is something they might be interested in as a solution for the mentioned EP document and long standing issues like #137
Beta Was this translation helpful? Give feedback.
All reactions