4 ms·
re-frame still adds way too much boilerplate for my tastes, especially on solo projects. I personally greatly prefer to use reagent directly over using re-frame
by hellofunk 6y ago
re-frame still adds way too much boilerplate for my tastes, especially on solo projects. I personally greatly prefer to use reagent directly over using re-frame.
- dancek 6y agoWe've had a great experience building a mid-size app with re-frame. Sure, writing subscription and event handlers and wiring it all together seems like a lot of boilerplate when you could just fetch().then(), but in the long run the architecture really pays off. It's not perfect, I do lament the boilerplateyness myself, but I have not seen anything better in my decade of web dev.
- snorremd 6y agoI think one thing re-frame does well is cascading events. One event might trigger other events, etc. There is also a library for orchestrating re-frame events: https://github.com/day8/re-frame-async-flow-fx https://github.com/day8/re-frame-async-flow-fx I think using re-frame rather than just building event loops yourself with channels and atoms give you some advantage in terms of existing libraries and utilities.
- pgt 6y agoYes. I now use Rum + Datascript + core.async for event sourcing. Here is the entirety of my reactive event-loop handling, inspired by Tonsky's Cat Chat (https://tonsky.me/blog/datascript-chat/ https://tonsky.me/blog/datascript-chat/): ; One Macro in events.clj: (defmacro go-loop-sub [pub key binding & body] (let [[db-bind & bindings] binding] `(let [ch# (cljs.core.async/chan)] (cljs.core.async/sub ~pub ~key ch#) (go-loop [] (let [event# (rest (cljs.core.async/<! ch#)) ~db-bind @yourproject.data.core/conn ~(vec bindings) event# result# (do ~@body)] (when result# (yourproject.data.core/transact! yourproject.data.core/conn result#))))) (recur))))) ;; Usage (at top of core file) (defonce conn (d/create-conn schema)) (defonce event-bus (async/chan)) (defonce event-pub (async/pub event-bus first)) ;; For each event you want to dispatch on: (go-loop-sub event-pub :todo/add-item [db {:as data :keys [text]}] ;; Query db here. Any tx-data you return will get transacted. [{:db/id -1 :todo/text text}]) ;; To display some reactive queries in DataScript: (rum/defc root-component < rum/reactive [conn] (let [db (rum/react conn) todos (d/q '[:find ?todo ?text :where [?todo :todo/text ?text]] db)] [:div "Todos: " (pr-str todos)])) That's it. You don't need re-frame.
- freshhawk 6y agoI use those same 3 in a similar way, it's great. I do really appreciate the design of the effects/coeffects concept in re-frame, I often use that concept. I just don't find I ever need re-frame.
- capableweb 6y agoHm, really? Maybe you're missing a layer of indirection if that's so? Usually I end up wrapping things myself so I have one "setup-handler :name" function/macro that creates the subscription and event db handler for me. There are also existing libraries that does this for you, if writing it yourself is not wanted. One example of such library: https://gitlab.com/nikperic/reframe-utils https://gitlab.com/nikperic/reframe-utils `reg-basic-sub` has this outcome: (reg-basic-sub :common/active-page) ;; Equivalent to (reg-basic-sub :common/active-page :common/active-page) ;; Equivalent to (reg-sub :common/active-page (fn [db _] (:common/active-page db)))
- rlander 6y agoFor solo projects that don’t need all the boilerplate I think Hoplon is an even better option (there’s a Luminus profile for it). It’s kinda like Svelte: it doesn’t use a vdom and makes interacting with the actual dom really simple: http://hoplon.io/ http://hoplon.io/