Fork me on GitHub
Drew Verlee20:08:41

If you want a dispatch to be attached to a component, do you just call it at the top? (Defn foo [] (dispatch...)) Put another way, what's the best way to get the same functionality as reacts useEffect?


Using a form-3 reagent component, I suppose


use effect does an effect and also registers how to clean that effect up


so its not 1-1 without some work


but if what you are tying is a dispatch, I would focus on deciding what technique you think is best for local component state


I havent figured out a perfect one yet, but I'm leaning toward a system where a component has "nested handlers" manually constructed

Drew Verlee20:08:15

Thanks, that makes sense. hmm. was hoping to avoid the lifecycle hooks.


i.e. its not truly local, it lives in the db and drives effects that get wrapped into the global scope

Drew Verlee20:08:40

Having some ajax call based on a component is a fairly common need, are people normally solving that with the form 3 comopnent?

Drew Verlee20:08:09

The alternative is to try and gatekeep/call before every path to that component, which isn't great.


The other alternative is to not use reagent and instead use helix, which fits with react's render model and lets you use useEffect


but idk how well that interacts with other parts of re-frame


You could also use useEffect directly with reagent, though I agree helix is probably better if you’ll be doing that a lot,


You can also have both helix and reagent in the same project easily enough


> Having some ajax call based on a component is a fairly common need, are people normally solving that with the form 3 comopnent? I find myself occasionally using form 3 components for this. I try to avoid it when I can. Most of the time I'm able to drive these kinds of effects by the same user actions that would bring those components into view, I.E. user clicks a tab, which fires off a series of events and maybe an ajax request, my component in question is also rendered. Sometimes it's really difficult to avoid and I have to use a form 3 component. The reagent macro provides a convenient syntax for this, and allows you to include a finally block that is executed when the component is destroyed. Outside of that I rarely reach to react lifecycle stuff (unless I'm dealing with 3rd party react components). I might do something like

(defn my-comp
  (r/with-let [_ (rf/dispatch [::fetch])]
    [:div @(rf/subscribe [::stuff-that-was-fetched])]
      (rf/dispatch [::clean-up-app-db]))))

Drew Verlee13:08:03

Attaching the ajax request to something other then the component doesn't make sense to me in this case. The component needs that information. If i put it on the action that changes the route (e.g on-click on a href) then if they do a full refresh that data might not be there, sense they didnt' follow that link.


Yes. It's not always possible to allow them to be user driven unfortunately. Sometimes a utility component comes in handy for decomposing the lifecycle management stuff and the view logic.

(defn setup-teardown-component
  [component {:keys [dispatch-event cleanup-event]}]
  (r/with-let [_ (rf/dispatch dispatch-event)]
    (finally (rf/dispatch cleanup-event)))

;; later in your view somewhere
  [my-pure-view {:a-subscription [::stuff-that-was-fetched]}]
  {:dispatch-event [::fetch]
   :cleanup-event [::clean-up-app-db]}]


I find that can be useful when the component is used in multiple places, the dispatches might look a little different so depending on the context you have the same view, but different events and subscriptions to provide the data. Separating the component itself from the events and subscriptions is a hard problem to solve I've found. Too many arguments can get messy and hard to trace as a component evolves over time. Inlining too many events and subscriptions makes the component hard or impossible to reuse. That's not totally related to your question but something I try to consider when I find myself reaching for form 3 components like this.