-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integration with re-frame and subscriber abstraction #4
Comments
Well, Posh's But why do that when instead of using the limited query syntax of So I think Posh's |
Hi @mpdairy ;) Thanks for responding so quickly. I prefer the subscriber notion since it makes the intention clear (by name) and introduces a level of intermediation for increased flexibility/reuse (in case same subscriber logic is shared between multiple components) etc. I'd like to extend your ToDo app with re-frame integration and start experimenting with the new datsync lib as well at some point (when it reaches more maturity and has some docs/examples) ;) Besides re-frame adds so much more to the equation, such as a very sane flow/cycle of event/signal streams and chain reactions etc. Having them as separate functions, also makes it easy to add "middleware" etc. to wrap them with functions, build them via macros etc. Having this logic "locked" inside a component will become a pain/limitation for more complex systems IMO. Cheers! |
How has this been going @kristianmandrup? I am writing a medium-ish reframe app in my spare time to evaluate its potential for enterprise scale apps down the road. Datomic has always interested me, but I've never found a matching use case until reagent/reframe. I agree with your points about decoupling pull (some complex processing) from subscribe (just give me the data, I'm a stupid component). Any major hiccups / glitches along the way? |
@aft-luke I haven't yet tried... I recommend taking the posh todo app, strip away as much as you can and go from there. Then polish the UI as well, perhaps using the datascript-todo app as a baseline. I'm writing a book on Datascript + friends ;) Feel free to contribute! |
@aft-luke, another person, @handojin, mentioned they were using posh with re-frame and re-com successfully |
@mpdairy @aft-luke Please reference whatever sample repo/projects using these kinds of combis. Thanks :) |
he mentions it at the bottom of this thread: #5 |
Sorry. The thing I'm working on is not public but FWIW I'm doing nothing 'special', just using posh/pull and posh/q inside the re-frame subscriptions & datascript/transact inside the re-frame handlers. Seems to work well but I haven't tested perf. etc. If you like I'll see if I can whip up a quick demo repo. |
Thanks @handojin :) |
FWIW I actually prefer Posh's way to handle subscriptions. The only thing I kind of "envy" from re-frame is the indirection and declarativeness added at the event/mutation step. That seems like it would help with testing complex interfaces. It also makes it more natural to do the right thing when performing requests to the server: that is, perform the ensuing mutations on the db at the time the request completes, not on the db at the time when the request was started. I imagine that would be very easy to implement on your own, so I'm not sure it merits library support, or that this library needs be Posh anyway. For some projects it may make more sense to just perform the transactions in the event handlers. Posh makes time travel and undo easy even if you do this; just keep references to old dbs. |
De gustibus, non est disputandum :) |
@aranhoide It is my general experience (and good practice) to keep things separated in order for easier refactoring, reuse, testing, overview etc. etc. Of course it is always a balance. Break em up when it makes sense, keep em locked up when they are simple enough together... |
@handojin @kristianmandrup: true. I'm not arguing against integrating with re-frame. I think, though, that such integration can be layered on top of the existing interface. Whether that is done in a different project or as an optional part of Posh seems less important to me, but I think the current interface should be preserved either way. I like re-frame's choices, but I deeply appreciate the fact that Posh seems less opinionated. For what it does, Posh's interface seems kind of inevitable, and a great building block for more opinionated packages. |
FYI, I've been extracting something that looks a bit like re-frame for posh as datreactor, part of the datsys/datview stack. Initially it was going to be bundled with datview, but I realized it might be something people would want to use on it's own, and that would also help make datsync more automated on the client side, without requiring datview necessarily. So check it out if you're interested. Note though; It's really just a mock of re-frame. I didn't like some of the decisions re-frame made about how it tracked state, and wanted something more component friendly. Ultimately though, I'd like to see if we can get these things to plug in more directly and simply/easily to re-frame itself, since there seem to be a lot of things building around that now. |
Cool :) Thanks mate! I just got back from 3 months in America. Now I have time to work on this again... |
Awesome! Cheers! |
Just posted a quick outline on the wiki of how I've been approaching integration. Thoughts, questions and criticism welcome |
I've spent a lot of time with this issue and want to share it now. For integrate posh and re-frame we need only the ways to write subscriptions and handlers. Subscriptions: (reg-sub-raw
:task-ids
(fn [_ _]
(q '[ :find [?tid ...]
:where [?tid :task/title]] conn)))
;; Usage
...
(let [task-ids (subscribe [:task-ids])]
[:span (str @task-ids)])
... We have to use For write handlers I've introduced an effect and coeffect: (reg-fx
:transact
(fn [datoms]
(transact! conn datoms))) With this effect one can execute transactions in re-frame way, declaratively (reg-event-fx
:update-task
(fn [_ [_ id path value]]
{ :transact [{ :db/id id
path value }] }))
;; Usage
...
[:button { :on-click #(dispatch [:update-task task-id :task/title new-title]) }] If you want to get DataScript database as a parameter in a handler you can declare co-effect (reg-cofx
:ds
(fn [coeffects _]
(assoc coeffects :ds conn))) and use it in that way: (reg-event-fx
:event-name
[(inject-cofx :ds)]
(fn [{:keys [ds]} [_ id path value]] ;; Now you have DataScript connection here, you can find any data you need but please don't transact anything
{ :transact [[:db/add id path value]] })) For more details, you can look at my repo / subscriptions / handlers @Conaws This solution allows one to not inject Datascript database into the re-frame but even have DataScript as a single source of true. The problem with the regular Hope it'll help |
Here the helper function (defn reg-event-ds
([k interceptors handler]
(reg-event-fx
k
(into [] (concat [(inject-cofx :ds)] interceptors))
(fn [{:keys [ds]} signal]
{ :transact (handler @ds signal) })))
([k handler]
(reg-event-ds k [] handler))) It will allow us to write handlers in this way: (reg-event-ds
:update-task ;; Event name
(fn [ds [_ id path value]] ;; Function that gets datascript database and signal
[[:db/add id path value]])) ;; and returns transaction It works exactly the same as re-frame |
I've just released a library that allows combining re-frame and DataScript together DataFrame |
Looks like Posh would fir perfectly in combination with Reagent and Reframe, however from the docs in your readme you state that the Posh methods are intended for use inside the Reagent components themselves, where as re-frame is based on subscribers which subscribe to changes in the global app state (via queries).
What are your thoughts on this? Can posh be used with re-frame? Any examples of such integration? Thanks :)
The text was updated successfully, but these errors were encountered: