Last active
June 6, 2017 07:56
-
-
Save metametadata/3b4e9d5d767dfdfe85ad7f3773696a60 to your computer and use it in GitHub Desktop.
Fixing of caret/cursor jumps in text inputs of cljsjs.react-bootstrap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns app.components.react-bootstrap | |
(:require [cljsjs.react-bootstrap] | |
[reagent.core :as r])) | |
(def Alert (r/adapt-react-class (.-Alert js/ReactBootstrap))) | |
(def Button (r/adapt-react-class (.-Button js/ReactBootstrap))) | |
; ... | |
(def FormControl (r/adapt-react-class (.-FormControl js/ReactBootstrap))) ; WARNING: use FormControlFixed for text input controls instead | |
(defn FormControlFixed | |
"FormControl without cursor jumps in text/textarea elements. Problem explained: | |
https://stackoverflow.com/questions/28922275/in-reactjs-why-does-setstate-behave-differently-when-called-synchronously/28922465#28922465 | |
I haven't tested it much in IE yet, so if it breaks in IE see this: https://github.com/tonsky/rum/issues/86 | |
Usage example: | |
[FormControlFixed {:type :text | |
:value @ui-value | |
:max-length 10 | |
:on-change #(on-change-text (.. % -target -value))}]" | |
[{:keys [value on-change] :as _props}] | |
{:pre [(ifn? on-change)]} | |
(let [local-value (atom value)] ; regular atom is used instead of React's state to better control when renders should be triggered | |
(r/create-class | |
{:display-name "FormControlFixed" | |
:should-component-update (fn [_ [_ old-props] [_ new-props]] | |
; Update only if value is different from the rendered one or... | |
(if (not= (:value new-props) @local-value) | |
(do | |
(reset! local-value (:value new-props)) | |
true) | |
; other props changed | |
(not= (dissoc new-props :value) | |
(dissoc old-props :value)))) | |
:render (fn [this] | |
[FormControl (-> (r/props this) | |
; use value only from the local atom | |
(assoc :value @local-value) | |
(update :on-change | |
(fn wrap-on-change [original-on-change] | |
(fn wrapped-on-change [e] | |
; render immediately to sync DOM and virtual DOM | |
(reset! local-value (.. e -target -value)) | |
(r/force-update this) | |
; this will presumably update the value in global state atom | |
(original-on-change e)))))])}))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment