Fork me on GitHub

Thanks, I will review. I found the discussion quite useful.


One question I have is about the line “Engineered to avoid core.async problems!” I’d like to know what those problems are. core.async is widely used in Om apps, maybe Reagent too; it is fundamental to many of the classic Om tutorials, and I’ve never had any problems using it in the context of a React-backed app (or any other context). If there are specific solutions that Re-frame adds to its async mechanism that are designed to “fix” something in core.async, it would be very useful to know exactly what that is.


Another useful thing to do on the FAQ is when you use a term like “interceptor” (vs middleware), maybe link to an explanation of what this term means in Re-frame. By itself, it’s not a term most would understand, so the advantage that point is making probably gets lost on someone not familiar with re-frame.


There's an infinite amount of cross referencing possible.


That’s a good link; I’d recommend linking directly to that in the async paragraph.


@lovuikeng Just added re-frame-trace to re-frame-template. lein new re-frame myapp +trace


looks like i used an old version of trace tho, whoops


ok, now it is using the latest re-frame-trace


thank you, @gadfly361 that's nice of you 🙂


@gadfly361 re-frame-trace is useful but still a bit fresh. It can provide some interesting insight, but I'm cautious about recommending it too highly. BUT it should mature to the point of being really useful over the next week or so. We have plans for pushing it the last mile.


@mikethompson Ahh gotcha, sorry for adding to template a bit prematurely


Not at all. I don't think there is a problem at all


It might be awesome very soon, we hope.


And even right now, it is useful in some cases


I just don't want anyone getting turned off it because their first experience was clunky.


So, sounding the warning


Yes, @U051KLSJF been saying the same, thank you @mikethompson


iirc core.async was removed from re-frame core event handling because it wasn’t performant but there is no reason not to use it elsewhere in a re-frame app. i use js promises for promise-like things, because i prefer the way they compose, and core.async for stream-like things


interesting, you prefer JS interop for some async matters?


i’m using promesa for promises, which uses bluebird under the hood, and cats for the mlet and alet composition


which mirrors our manifold+cats usage on the back-end


@mhuebert wow thanks for this overview


Still trying to digest it all, but clarifies the picture


@wpcarro you’re welcome! in the end, not sure if it helps with your specific debugging problem, but after I implemented some of this myself I was surprised how simple the underlying technique is


another thing that has confused me in the past is how calling a reagent component as a function, vs. putting it as the first element in a hiccup vector, changes where the reactivity happens. eg toy example: given this reagent view, which returns plain hiccup:

(defn show-count [id]
  [:div @(subscribe [:counter id])])
calling as function:
(doall (map show-count @all-counter-ids))
vs. putting in hiccup vector:
(doall (for [id @all-counter-ids]
              [show-count id]))


It surprised me (but is logical when you think about it) that in the 1st version, mapping with the function, all of the counter ID subscriptions are actually bound to the same reagent view (the parent view that map is sitting in), so that whole view, with all the counters, will re-render when any of them change.


whereas when you put them in their own independent vectors, each of those hiccup vectors maintains its own ‘listener’ to its counter, so if one counter changes, only that part of the view updates.


That feels surprising to me


This only comes up when dealing with function calls vs. hiccup forms?


ie (render-thyself) vs [render-thyself]


not only that, but this would be a common case. the general thing is that we always want to know which component is ‘active’ (which Reaction is sitting on *ratom-context*, collecting dependencies) when a given ratom or subscription is dereferenced.


Reagent doesn’t use a complicated macro, it just reads whatever data you give it. so if you type (doall (map show-count @all-counter-ids)), by the time reagent sees it, all that’s left is the expanded form, eg. ’([:div 5], [:div 3])`: all of the (subscribe [:counter id]) forms have already been dereferenced, the show-count function is gone and has already returned a value. So there was no way for Reagent to somehow bind them to the show-count function.


Whereas, if you pass Reagent the vector [show-count 5], it is able to say “hey, I’ve got this function called show-count and one argument, 5. I’m going to call the show-count function and keep track of all the dependencies that are read while it is evaluated.”


IMO this stuff is some of the most tricky to get the hang of with reagent because it’s quite invisible.


@mhuebert that makes sense. I’d agree that it feels a bit like voodoo to me at times


As a former React developer I only recall needing to keep track of the flow of props into components most of the time…


But I think React differs from ReAgent in that ReAgent has the potential for more targeted DOM updates because of the dependency tracking that Reactions allow. Is that fair to say?


I haven’t used it directly but I think something like MobX might be the closest js-react parallel


when used as intended, yes Reagent can quite narrowly re-render just the parts of the view that depend on the state that changed