Fork me on GitHub

Does anyone know if the changes in Reagent 0.6 broke anything in re-frame?


@mattgeb I don't think it did, why?


Looking forward to that addition, it makes conditional dispatches in dispatch-n a lot cleaner (as is evident in your examples)


@yedi and @curlyfry Yes, ineed, sorry about that ... the docs are ahead of the release schedule there.


You can get that functionality now if you monkey patch the dispatch-n effect handler in your own code

  (fn [value]
    (if-not (sequential? value)
      (re-frame.core/console :error "re-frame: ignoring bad :dispatch-n value. Expected a collection, got got:" value)
      (doseq [event (remove nil? value)] (router/dispatch event)))))


And then remember to remove your money patch after the next release


thanks homies


Hi, all. I had a strange experience with re-frame subscriptions a few days ago, and wonder if there is something I’ve missed. In general terms: In ns “foo.subs” I used reg-sub to register subscription :subA. Than ns was required in “foo.core” that also utilized this subscription in a component. The problem was that I got an error telling me that there was no registered subscription for :subA. My workaround was to move this reg-sub to the top of ns foo.core, but I find it strange that I had to do this as. Any thoughts?


@curlyfry Cool! Was just worried cuz the 0.6 update mentioned "By the way, we changed a BUNCH of stuff to reflect the new JS library interop. There's probably bugs!".


Are there any publicly available examples of larger re-frame applications? I'm looking for a bit more insight in how folks structure things than the Basic App Structure ( page offers.


I've ended up doing kind of the opposite (e.g. I have handlers/panel.cljs + views/panel.cljs for my different areas) and I was curious to see what others have done.


@mokr It’s strange indeed. How do you use the subscription ? (subscribe [:subA]) ?


@jvuillermet Thanks for confirming. Yes, in essence that’s the code I use, but via a “listen” helper that does the deref. I believe the docs/examples also calls that kind of helper “<sub”


hi! I’m starting out with re-frame, and I’ve used a pattern like this to handle navigation between different views:


I’m having doubts on how to add some initialization step required when a view gets activated


for example if a view displays a list of elements that comes from the backend, I want that list to be fetched and saved in the app db every time that view becomes active


would it be ok to just dispatch an initialization event inside the view? e.g.:

(defn channel-list-view
  (re-frame/dispatch [:channels-load])
  (let [channels @(re-frame/subscribe [:channels])]
     [:h2 "Channels"]
     (if (empty? channels)
       [:p "There are no channels yet."]
        (map channel-item-view channels)])]))


@facundo i'm pretty new to re-frame as well so take my advice relatively lightly


but I would suggest you look into form-2 reagent components


which are basically functions that return the render functions (which in turn return the hiccup for you component)


if you use a form-2 component, in the outer function you can dispatch events that run only once when you component gets mounted


so dispatch events fo rfetching the data in the outer fn and then subscribe to that date in the inner/render fn


mmm I’ve used those but I’m not sure those would match my need if I understood right how mounting works


let’s say I do it like that, if a new element gets added to the backend after I’ve loaded my app, my list won’t be refreshed until I do a full page refresh


for example, if I’m standing in the list, change the view to edit one of the elements and come back to the list


I want the changed element to be updated


(maybe I’m thinking this backwards, I haven’t done front end in a while)


well the list will be populated from the data in the global app-state, so if that changes then your component would update correctly


so as long as you have the correct logic for updating the global app-db then you should be fine


yeah that’s right, but what about someone else updating it


does it make sense to want the data to be refreshed without having to reload the app?


right then seems like you'd have to implement some sort of polling / websockets thing that watches for changes from the backend and updates your app-db accordingly


the great thing about reframe and react is that the view should always display what the current state is, so as long as you're managing your app-db correctly you don't have to worry about explicitly updating your view


if that makes sense


mmm so if you were to edit an element of the list, you’d both send the corresponding request to the server and manually update it in the app-db?


(my intuition is to just send the PUT request and emit an event that causes the data to be fetched again from the server)


the way i'd do it is send a request to the backend and then flip some loading/pending state to show the user that something is happening


when the request returns from the backend, usually it would have the updated list of items. so you'd then update the app-db with the new list. (as well as remove the loading state)


so when the requests returns the app-db gets updated which automatically rerenders your view with the correct state


ok, I thank that generally makes sense


(i wouldn't modify the data in the app-db prematurely just in case the request errors in the backend. you don't really want your local app-db to have changes that aren't reflected in the server... but that can be figured out on a case by case basis. sometimes its merited)


I still wonder about the case when someone else modifying the data


yea you'll have to implement some kind of polling thing that listens for changes from your server


and then updates the app-db. which would automatically force the view to be rerendered


i don't have too much experience implementing polling but there are tons of examples / libraries online for doing it


I think it’s overkill for my case (it’s a simple crud and no special reason to think there will be more than one user touching the same data)


I can do just fine with just loading the data when the view is mounted


word sounds good


just to understand a bit more, would you say that doing it like in the snippet I’ve posted below is not a good idea?


as in it doesn’t make sense to be dispatching everytime a view function is called or something like that


i would do something like this instead

(defn channel-list-view
  (re-frame/dispatch [:channels-load])
  (fn []
    (let [channels @(re-frame/subscribe [:channels])]
       [:h2 "Channels"]
       (if (empty? channels)
         [:p "There are no channels yet."]
          (map channel-item-view channels)])])))


yeah, I know about those, just that my version does achieve that thing of always keep in sync with the backend. I wonder if it’s conceptually wrong to do it like that


well that would only update the state whenever your view rerenders


so it wouldn't be able to instantly know about new changes to the db


but it also subscribes to [:channels]


also depending on how often the view is being rerendered, you'll probably not want to send a request to the backend everytime


:channels-load just populates channels in the app-db


right so basically what that would do is:


1. when the view renders, fetch the channels from the backend.


2. rerender the view with the new channels (which would cause another request to the backend)


3. return to step 2 if the channels data changes if not it just sits there


4. waits until your user does something to change the view or cause it to rerender, once that happens return back to 1.


yeah it’s kind of weird that when it does change you both render the view and trigger the channel fetching again


so while the app is in state 3, it won't automatically know about new changes to your backend db. you'd have to wait for the user to make the view rerender somehow


yeah I don’t really need auto updating


just not showing an outdated list when I do click on “show me the list"


yea i think you would just want form-2 components for that. and only dispatch channel load when the list view mounts


@facundo: I'd try and start the data fetch from some event handler, I mean not necessarily right there but probably dispatching an event to do so. It could be a route change handler (if going to this list, and/or updating and going back to it involves a change in route) or an :update-item event. Did you see the recent post from Eric Normand the first "thing reacters do that re-framers avoid" is basically about this 🙂


oo nice article @nberger


yep, it's good, as always coming from Eric 🙂


thanks @yedi and @nberger I’ll take a look at that article


heh the first point answers exactly my question 🙂


so what I did based on the article’s advice is to create an event like this

 (fn [_ _]
   {:dispatch-n [[:channels-load]
                 [:switch-view :channel-list]]}))


and other events dispatch [:switch-to-channel-list] instead of [:switch-view :channel-list] directly


it doesn’t feel ideal, but definitely better than having the view do the dispatch