Hacker News new | ask | show | jobs
by pinchhit 2159 days ago
Three things that would make re-frame better, if you want them:

- A supported/blessed way to switch out the entire app-db entirely for the purposes of testing

- Use of symbols rather than namespaced keywords for function dispatch

- Docs that give alternate strategies for code organization (fine to have the events.cljs convention, but would be nice to see some viewpoints like having one per child ns similar to angular's code organization model.)

1 comments

Answers to your three points:

  - I'm wondering if re-frame-test might help? 
  - That ship has sailed a long time ago. And, even if it hadn't, I diagree that symbols would be better. 
  - I'm unfamiliar with angular's code. The Resources section lists larger apps which you can inspect.
I'll try re-frame-test, thanks! If it doesn't do something like `(with-redefs [re-frame.db/app-db (reagent/atom {})] ...)` it is still open to this bug, though. Because the call to `dispatch` happens inside of a callback the test library has no way to signal that future dispatches coming from a different function context should not be put on the same queue.

It'd be hard to change that aspect of the API now, and I wouldn't recommend you do it; but right now, editor completion and new-user understanding is just better on the reagent side. They do this:

    (defn assoc-foo [db bar]
      (assoc db :foo bar))
    
    (defn fetch-new-foo [db bar]
      (go
        (let [bar (<! (get-bar)]
          (swap! db assoc-foo bar))))
    
    (swap! db assoc-foo bar)
    (fetch-new-foo db bar)
whereas re-frame would make you do this:

    (re-frame/reg-event-db
      ::assoc-foo
      (fn [db [_ bar]]
        (assoc db :foo bar)))
    
    (re-frame/reg-fx
      ::pull-from-channel
      (fn [{:keys [f event]}]
        (go
          (let [resp (<! (f))]
            (re-frame/dispatch (conj event resp))))))
    
    (re-frame/reg-event-fx
      ::fetch-new-foo
      (fn [_ _]
        {:pull-from-channel {:f get-bar
                             :event [::assoc-foo]}}))
    
    (dispatch [::assoc-foo bar])
    (dispatch [::fetch-new-foo])
The first one has a lot going for it; swap! is part of the standard library, has a bunch of docs for free, etc.; any clojure editor will pick up on the use of assoc-foo as a function and give you arity warnings if you pass too many parameters, etc.

I've looked at the larger apps - the way I've seen people be most successful if if they have a child namespace with events, subs, & views laid out on a per namespace basis (`my-ns.events, my-ns.subs, my-other-ns.events, my-other-ns.subs`.) Partially due to the tone the docs take, there's always some pushback as to whether that's the re-frame way to do things, and I'd love to just be able to avoid that whole conversation in the future.