Pablo Fernandez
Pablo Fernandez

Reputation: 287780

How to have proper bidirectional binding on ClojureScript with Reagent?

I'm writing a wrapper for React Toolbox for ClojureScript/Reagent called Reagent Toolbox. In React Toolbox, there's an input component that's used like this:

<Input type='text' 
       label='Name' 
       name='name' value={this.state.name}
       onChange={this.handleChange.bind(this, 'name')}
       maxLength={16 } />

I created a Reagent component around that React component like this:

(def input (reagent/adapt-react-class (.-Input js/ReactToolbox)))

so that I can use it like this:

[reagent-toolbox.core/input {:label      "Name"
                             :name       "name"
                             :type       "text"
                             :value      @name
                             :max-length 16
                             :on-change  (fn [value event] (reset! name value))}]    

But unlike the React version, in the Reagent version, each key press on the input causes the component to be re-rendered making the cursor jump to the end. You can experience that effect here: http://reagent-toolbox-docs.dashman.tech/input

Whan am I doing wrong? What am I missing?

Upvotes: 2

Views: 223

Answers (1)

Davin Tryon
Davin Tryon

Reputation: 67326

I also encountered this error in the past, but it took me a while to remember why this occurs.

This SO post explains the underlying problem. This occurs in Reagent, because all Reagent re-renders are async. Therefore, every controlled input explicitly sets the .valid attribute on the DOM (which, depending on the browser, places the cursor at the end).

This Reagent issue goes into the most detail about this problem and finally merges a solution for Reagent's inputs.

The short answer seems to be that simply using reagent/adapt-react-class here doesn't seem to be enough. It looks like you will have to wrap the adapted class and apply the same fix by inspecting selectionStart and selectionEnd and repositioning the cursor.

Upvotes: 1

Related Questions