reagent

A minimalistic ClojureScript interface to React.js http://reagent-project.github.io/
2020-05-12T08:52:27.433700Z

Well, when I try to run it in a browser context, a basic test I ran apparently gets confused with the generated result page, so I was mostly thinking about using it with jsdom. I'll give karma a shot first, though and see if that just works.

2020-05-12T08:52:36.433900Z

Thanks everybody for the input.

Mark Wardle 2020-05-12T10:06:45.434100Z

Ah I see. Thank you. I assumed the reagent macro did all of the js getElementById and render for an arbitrary component. So essentially I have to create a reagent “form 3” type and run getElementById and render from there into the DOM fragment? Thanks I’ll give this a try.

2020-05-12T12:05:51.434300Z

And of course it turns out that not react-testing-library was confused but my test and it works as a browser-test just fine.

2020-05-12T14:38:30.435900Z

reading the channel makes me question about how I use reagent and re-frame.. this is a typical view function from my app

2020-05-12T14:38:33.436100Z

(defn main-panel []
  (let [fund-filters-loaded? @(rf/subscribe [:fund.filters.subs/loaded])
        logged-profile @(rf/subscribe [:logged-profile])]
    [:<>
     [chart]
     (if fund-filters-loaded?
       [:<>
        [filters {:suspended-enabled? false
                  :custom-filter #(custom-filter logged-profile)}]
        [fund-list callback]]
       [:div "loading..."])]))

2020-05-12T14:39:03.436600Z

this is a form-1 component according to reagent documentation

2020-05-12T14:39:21.437100Z

my question is, should it be form-2 and return a function instead?

lilactown 2020-05-12T14:43:24.438Z

@wvelezva what you wrote works. re-frame caches subscriptions, so when your component re-renders it will get the same subscription value every time

lilactown 2020-05-12T14:43:52.438600Z

the reason you'd use a form-2 is it if you wanted something to only run on component mount (first render)

lilactown 2020-05-12T14:44:22.439300Z

e.g.:

(defn my-component []
  (let [count (r/atom 0)]
    [:button {:on-click #(swap! count inc)} @count]))

lilactown 2020-05-12T14:44:40.439800Z

☝️ that would re-create the count atom every render, so it would always say "0"

lilactown 2020-05-12T14:45:23.440900Z

(defn my-component []
  (let [count (r/atom 0)]
    (fn []
      [:button {:on-click #(swap! count inc)} @count])))
☝️ that will create the count atom on first render, and then only run the inner function each subsequent one

2020-05-12T14:46:36.441600Z

I understand, and that is not desirable so in my case with the subscriptions?

2020-05-12T14:47:53.442400Z

and only make the dereference in the inner fn?

2020-05-12T14:47:54.442600Z

(defn main-panel []
  (let [fund-filters-loaded? (rf/subscribe [:fund.filters.subs/loaded])
        logged-profile (rf/subscribe [:logged-profile])]
    (fn []
      [:<>
       [chart]
       (if @fund-filters-loaded?
         [:<>
          [filters {:suspended-enabled? false
                    :custom-filter #(custom-filter @logged-profile)}]
          [fund-list callback]]
         [:div "loading..."])])))

lilactown 2020-05-12T14:48:21.443100Z

like I said above, you can use either a form-1 or form-2 because re-frame caches subscriptions

lilactown 2020-05-12T14:48:29.443300Z

(rf/subscribe [:fund.filters.subs/loaded]) will return the same thing every time

lilactown 2020-05-12T14:48:40.443600Z

it will only create the subscription once

lilactown 2020-05-12T14:48:47.444Z

so you may use it in a form-1

2020-05-12T14:49:10.444800Z

so is a matter of taste?

v 2020-05-12T14:49:12.444900Z

use form-2 if and only if, you are dealing with local states i.e using reagent to manage form state

lilactown 2020-05-12T14:49:22.445300Z

yes it's a matter of taste

v 2020-05-12T14:49:24.445400Z

other than that its preferred to use form 1

v 2020-05-12T14:49:34.445800Z

form 1 makes component simpler

v 2020-05-12T14:49:51.446500Z

since it only does one thing, renders component

2020-05-12T14:50:10.446900Z

😌

2020-05-12T14:50:35.447200Z

thanks a lot!

v 2020-05-12T14:50:44.447500Z

how ever, if you still want to use form 1 component while managing local state

v 2020-05-12T14:50:46.447700Z

you can do that

v 2020-05-12T14:50:48.447900Z

there is a trick

2020-05-12T14:51:15.448300Z

I’m all ears….

v 2020-05-12T14:52:27.448600Z

(defn simple-form [args]
  (reagent/with-let
   [state (reagent/atom {:username ""})]
   [:form
    [:input {:type :text
             :placeholder :username
             :on-change #(swap! state assoc :username (-> % .-target .-value))
             :value (:username @state)}]]))

v 2020-05-12T14:52:46.449100Z

the trick is to wrap the component with with-let function

v 2020-05-12T14:53:00.449400Z

and voila, no more form-2

2020-05-12T14:57:27.451200Z

the code I inherited had those with-let plus the subscriptions, when I started learning I didn’t see any difference between with-let and the “simple” let so I adopted that style

2020-05-12T14:58:25.451700Z

thanks @lilactown and @vishal.gautam

1👍
Sean Poulter 2020-05-12T18:06:41.452800Z

Anyone know if it is possible to configure the React Dev Tools to highlight updates to Reagent components? 🤞