reagent

jmckitrick 2024-06-04T10:43:53.054319Z

I have a style question for you all, and I want to understand if there’s an underlying guiding principle to follow….

jmckitrick 2024-06-04T10:44:55.277509Z

When rendering a component with zero arguments, but with local state (let), when do you return a rendering function (fn) versus just the raw hiccup syntax (vector of components)?

jmckitrick 2024-06-04T10:46:58.432049Z

I should add that in re-frame code, many of those ‘let’ bindings are not actually local state (r/atom), but rather subscriptions, so that is subtly different but could make a big difference in the understanding of ‘local state’.

p-himik 2024-06-04T10:48:07.781349Z

A local state necessitates form-2, form-3, or r/with-let. So you cannot just return Hiccup, at all. Unless you don't use that state in the component itself and pass it to children. But I myself wouldn't call that state "local". Regarding re-frame - that's just not local state at all, it's global, by all accounts.

jmckitrick 2024-06-04T10:49:56.051139Z

Ok, that’s what I was thinking. With re-frame, it’s not necessary to return the fn like it would be with an atom of local state.

p-himik 2024-06-04T10:50:28.966369Z

Indeed.

Saket 2024-06-04T15:46:59.825179Z

@lucio I am using the lovely https://github.com/luciodale/fork library and facing a weird issue where while changing any character in an input field cursor moves to the end.

(defn- add-user-form [{:keys [values form-id handle-change handle-blur submitting? handle-submit]}]
  [:form {:id form-id
          :on-submit handle-submit}
   [:div.flex.flex-col.gap-4
    [:div.flex.max-w-lg.gap-4.items-center
     [label/label {:html-for :name} "Name"]
     [input/input {:id :name
                   :name "name"
                   :value (get values "name")
                   :on-change handle-change
                   :on-blur handle-blur}]]]])

(defn- add-client-comp []
  [drawer/drawer {:shouldScaleBackground true}
   [drawer/trigger {:asChild true}
    [button/button "Add Client"]]
   [drawer/content {:class "h-[60%]"}
    [:div.w-full
     [drawer/header
      [drawer/title "New Client"]
      [drawer/description "Just basic information about the user, you can update it later as well!"]]
     [:hr.mb-10]
     [:div.px-4
      [fork/form {:id ::add-user-form
                  :initial-values {"name" "Hello"}
                  :path [::add-user-form]
                  :prevent-default? true
                  :clean-on-unmount? true
                  :on-submit #(js/console.log %)
                  :on-blur #(js/console.log %)}
       add-user-form]]]]])
What am I doing wrong here?

p-himik 2024-06-04T16:11:17.437499Z

Just to make sure - are you using the latest version of Reagent?

Saket 2024-06-04T16:12:46.310959Z

No, I am on v1.1.1 🤔

Saket 2024-06-04T16:14:46.526209Z

The issue persists with reagent v1.2.0

p-himik 2024-06-04T16:23:53.228679Z

How do you use add-client-comp?

Saket 2024-06-04T16:26:39.870799Z

[:div.w-full.flex.gap-2
        [input/input {:class "bg-white max-w-64"
                      :type :text
                      :onChange (debounce
                                  (fn [evt]
                                    (reset! filter-string! (oget evt :target.value)))
                                  500)
                      :placeholder "Search for a client"}]
        [button/button {:class "ml-auto"
                        :variant :outline}
         "Bulk Import"]
        [add-client-comp]]
It's part of the bigger component. Pasted above a snippet from it

Saket 2024-06-04T16:28:15.609129Z

This is how the UI looks.

p-himik 2024-06-04T16:31:27.808069Z

It seems as if some of the parent components is re-rendered when only the form itself should be, as described in this section: https://github.com/luciodale/fork?tab=readme-ov-file#can-i-go-anonymous But that section doesn't cover your case. Maybe you have a :key somewhere that forces the whole relevant component tree to be re-rendered?

🤔 1
Saket 2024-06-04T16:31:57.748939Z

https://gist.github.com/Samy-33/3acfa0157a17d526ddf9b270e50b85ce The whole file ^ As I believe the above snippet isn't that helpful.

p-himik 2024-06-04T16:32:01.076139Z

Things like this are possible to debug with React DevTools, assuming you're using a compatible version of React. And if you don't, there's a way to install an older version of the extension.

👀 1
Saket 2024-06-04T17:32:06.414649Z

In handle-change fn https://github.com/luciodale/fork/blob/master/src/fork/core.cljs#L133-L137, we update the state. Which is passed to the form-component https://github.com/luciodale/fork/blob/master/src/fork/reagent.cljs#L88-L90. Wouldn't that cause the re-render of the form component, when anything in the input changes? This will in turn reset the cursor position, if I am not wrong. Also, rerender of the form component is caused by argv change. I believe that's pointing to the state change?

p-himik 2024-06-04T19:30:44.750569Z

argv is probably what r/argv returns - i.e. the whole Hiccup vector, including all the arguments and the children. > Wouldn't that cause the re-render of the form component, when anything in the input changes? Maybe? Sorry, don't have a brain capacity at the moment to carefully check.

🙇 1
😵‍💫 1
Lu 2024-08-16T09:45:28.054719Z

sorry to be late to the party but I’m not so much on clojurians… I think the problem lies in the drawer component.. that’s doing something that’s making the cursor jump.. usually there are props you can pass those components to prevent this problem..

Lu 2024-08-16T09:45:41.428039Z

I had a similar issue with a drawer component (Joy, MUI)

Lu 2024-08-16T09:45:59.950989Z

and the fix was to pass a disablePortal prop which does: The children will be under the DOM hierarchy of the parent component.

Lu 2024-08-16T09:46:31.953809Z

you get funky behaviours when the children are placed outside of your react tree

🙌 1
Lu 2024-08-16T09:46:40.099759Z

hope that helps

Saket 2024-08-16T09:47:07.969199Z

Thanks Lu. That does make sense. I'll try that and let you know

Lu 2024-08-16T09:47:23.025469Z

OFC man! 🙂

john 2024-06-06T13:42:51.047239Z

If on every input change, your logic is repeatedly writing the same old value into the current input value, instead of the new one, then you'll see that cursor behavior, iirc. Have you tried adding printlns inside the input handler to see what you're passing in?

🤔 1
Saket 2024-06-07T06:18:12.760069Z

I'll check this today..