reagent

hkjels 2023-04-17T08:09:05.259359Z

I'm wrapping a JavaScript library that expects react components as paramters. I can use reactify-component to pass reagent components in, but I then have to convert the arguments of the reagent-component with js->clj. Is there a way to wrap and generalize this conversion, so the end-user of this cljs library doesn't have to worry about the underlying js?

hkjels 2023-04-17T09:01:50.242389Z

(defn- react-flowify-component [component] (r/reactify-component (fn [args] (component (flowjs->clj args)))))

hkjels 2023-04-17T09:02:21.153629Z

something like this works for type-1 components, but not type-2

hkjels 2023-04-17T09:37:40.664599Z

I guess it would require a specialized compiler

p-himik 2023-04-17T09:44:15.781979Z

Why do you call component as a function instead of using []?

liebs 2023-04-17T17:05:55.176609Z

So I'm using refs for the first time and I have some questions. This is my adaptation of the example from https://react.dev/reference/react/forwardRef.

(def my-input
  (forwardRef (fn label [props ref]
                (let [props (assoc (js->clj props) :ref ref)]
                  (r/as-element [:label (get props "label") [:input props]])))))

(defn test-form []
  (let [ref (useRef nil)
        handle-click (fn [] (.. ref -current (focus)))]
    [:form
     [:> my-input {:label "Enter your name: " :ref ref}]
     [:button {:type :button :on-click handle-click} "Edit"]]))

(defn main []
  [:div [:f> test-form]])
It works, but several things are unclear to me. Why do I need to create a class-based component with :> to then pass into a functional component? I assume there must be a better/more correct way to do it. Why does this blow up if I pass ref in like [:> my-input {:label "Enter your name: "} ref] , which is how I would expect it to work?

p-himik 2023-04-17T17:39:34.683929Z

> Why do I need to create a class-based component with :> to then pass into a functional component? forwardRef returns a React component. To make React components work inside Reagent Hiccup, you need to use :>. It has nothing to do with the fact that test-from is a function component. You could've made it a class component and it would still have to use :>. > Why does this blow up if I pass ref in like [:> my-input {:label "Enter your name: "} ref] , which is how I would expect it to work? Because React expects for the ref to be a part of the props object. Hard to add more details without carefully going through the implementation (again, heh), but Reagent does some props/args juggling to make Reagent Hiccup work in a nice way. Seamless interop with React ecosystem is a second-class citizen.

liebs 2023-04-17T17:43:08.648499Z

Wouldn't using a class-based component cause the Invalid hook call error? Point nonetheless received about the props stuff, thanks.

p-himik 2023-04-17T17:49:41.790779Z

You're using the hook in test-form, which is a function component.

liebs 2023-04-17T17:56:11.519449Z

I see, misinterpreted your above comment. Thanks for the clarification.

馃憤 1
DrLj贸tsson 2023-04-17T20:11:08.989669Z

I'm a bit confused on how the :value and :default-value attributes of input elements in reagent / re-frame really work. For form elements that need an initial value, we have successfully followed this pattern [:input {:type :text :default-value @(rf/subscribe [:val]) :on-change (fn [ev] (rf/dispatch [:update-val (-> ev .-target .-value)}] As far as I understand, using :default-value here, prevents any flickering and delay when typing into the input, because the input does not actually "listen" for changes to the :val sub. However, I can't clear the input through a re-frame event, for that very reason. OTOH, I could use :value @(rf/subscribe [:val]) and then the value in app-db and the input are synced, and can be reset by an re-frame event. But if the dispatch or subscription are slow for some reason, one may experience lagging when typing into the input. Re-frame's re-com seems to handle the lagging using reagent atoms to represent internal and external values of the input. But re-com components come with other stuff that I don't want to use. My question is: what is the preferred and simplest way to manage inputs in a re-frame app? Should I use :default-value when I don't need two-way updates of the value and :value if I want external events to be able to change the value, but I will then risk laggy inputs? Or do I need to imitate re-com's more complex way of handling inputs?

p-himik 2023-04-17T20:12:35.797459Z

Have you tried dispatch-sync?

DrLj贸tsson 2023-04-17T20:13:46.531559Z

So, I have actually not experienced laggy typing even when using :value. But I guess that :dispatch-sync would solve that?

DrLj贸tsson 2023-04-17T20:14:57.322049Z

My question is more a principal one. Is there a "gold standard" to handle inputs? If no, what are the options under what scenarios?

p-himik 2023-04-17T20:16:27.858929Z

That's actually in the FAQ. :) https://day8.github.io/re-frame/FAQs/laggy-input/

DrLj贸tsson 2023-04-17T20:19:44.996389Z

Doh! I actually read that precise FAQ entry when I started re-frame development.

馃槃 1
DrLj贸tsson 2023-04-17T20:20:50.596679Z

But thank you for reminding me. 馃槈

馃憤 1
DrLj贸tsson 2023-04-17T20:22:36.989569Z

May I ask what option you use of the ones listed there? Does it depend on context?

p-himik 2023-04-17T20:24:10.915189Z

2 or 3, depending on the context. Not sure why, but often plain dispatch works just fine as well.

DrLj贸tsson 2023-04-17T20:31:30.440469Z

You never use :default-value?

p-himik 2023-04-17T20:34:34.085569Z

Nope.

DrLj贸tsson 2023-04-17T20:40:20.569339Z

Right. I鈥檝e tried to read the React docs to understand what defaultValue does but since I don鈥檛 understand React, I don鈥檛 understand that either.

DrLj贸tsson 2023-04-17T20:42:21.001299Z

Maybe I shouldn鈥檛 concern my brain with this if it is not important in a reagent / re-frame context

hifumi123 2023-04-17T21:38:02.685419Z

An alternative that isnt suggested in the docs: use uncontrolled state and hold a ref; then you can dispatch the values to your app-db on blur. This has the benefit of preventing re-renders per key press and is theoretically faster than using a local ratom or even hooks.

hifumi123 2023-04-17T21:38:30.329179Z

Of course this assumes there is a possibility to use uncontrolled state; otherwise this is not an option

p-himik 2023-04-17T21:39:01.495319Z

Isn't that exactly what the docs mean by "don't use on-change, and instead use on-blur"? And you don't really need refs for that.

hifumi123 2023-04-17T21:40:18.574359Z

the ref is to be able to access the actual dom node so you can pull values and/or do things like focus on error without holding a ratom or some data in app-db

hifumi123 2023-04-17T21:40:24.453069Z

and i guess you're right the docs do imply what i mentioned regarding on-blur