Comments (4)
To understand the behaviour you’ll need to understand all the layers involved.
I’ll start with the facts: if you want good UX with input box, you have to change its value inside on-change
listener. That’s how browsers work, you can’t change that. If you change input box value outside of listener, if you have any asynchronous behaviour (go block, batching, setTimeout 0, anything), your UX will sucks: flicker, lost cursor position, etc.
React, as you probably know, messes with input boxes. But if you have React’s on-change
callback that triggers re-rendering of the input box (or its parents) immediately inside on-change
callback it works just fine. No flickering.
Now why Reagent example works with go blocks. It probably doesn’t retain cursor position (does it? try to type in the middle of the text in the box), but has no flickering: you type a letter, nothing re-renders, some time later go block fires, input box content gets replaced. It might lag (if go blocks are busy, for example), but there’s no place for flicker. You just change A→B, single change, maybe delayed, but it’s atomic.
And then we have Rum. This is where things get ugly. Rum has batched rendering, meaning, rum/request-render
does not trigger React rendering immediately, instead, it waits for requestAnimationFrame
to occur, and triggers all batched changes then. If you understand what I was talking about above, you’ll see that would not work for input boxes: even for simplest cases ([:input {:value (rum/react *value), :on-change (fn [e] (reset! *value (.. e -target -value)))}]
) the re-rendering will be scheduled for some time later, meaning React will have to show not changed text field immediately after key press and change input box value later when animationFrame occurs. It flickers, it messes cursor position, it doesn’t work.
This is why David Nolen invented, and r0man copied this. This is a hack to work around that problem with async render: it lets you type anything to input box and it’ll show it immediately, and async render can change this value later. This works ok for normal text input, but is bad for any type of validation: you can see text flicker. Even worse, these hacked inputs are the only type of inputs you can have in sablono, and Rum uses sablono as its DSL for React elements.
One way to fight this is to force non-async re-render in an on-change
callback of such an input. Another way is to use native React input (via (js/React.createElement "input")
for example). See how I did it here.
This is way more complicated than it should be, of course. But it’s what you get if you build standing on the shoulders of the giants.
Let me highlight:
- Rum does allow
request-render
from anywhere - Reagent’s way of batching changes isn’t magic: you’ll lose your cursor position and see occasional lags
- Things are complicated when you need validation in input box: browser, React and your frontend framework (Reagent, Om, Rum) each adds their own complications
- The only perfect validation can be implemented with native
onChange
callback andpreventDefault
, avoiding React and later layers
from rum.
Thank you Nikita, I appreciate your comprehensive response. Is my understanding correct that, all React Framework will experience delay between keydown and the next animation frame. The only difference is that Reagent somehow prevents the text from showing in the input after keydown and before animation frame, while OM and Rum just does nothing between keydown and animation frame and just let the text appear. But ultimately all experiences the same delay.
from rum.
@robinchew Please try to repro this in 0.12.0-SNAPSHOT and report any issues to #205
from rum.
0.12.0 has been released
from rum.
Related Issues (20)
- rum/fragment with React components HOT 2
- optimizations :advanced (shadow-cljs) failing on simple :form :input
- defc error with shadow-cljs. Makes Rum unusable for me... :( HOT 22
- daiquiri: fragment? fails on vectors HOT 13
- Question about rendering performance when updating state asynchronously HOT 9
- should-update error
- Big performance regression between 0.11.5 and 0.12.3 HOT 9
- Server/client difference when rendering nil HOT 2
- require-lazy macro unnecessarily prescriptive about namespace/module structure HOT 1
- Error when use `rum/local` and `rum/use-callback` together HOT 2
- Hydration not fully compatible with React 18 HOT 4
- bind-context produces unfixable infer warnings HOT 3
- `with-key` and `with-ref` Removing children? HOT 2
- ClojureScript >=1.11.51 seems to break Rum HOT 4
- ClojureScript >=1.11.51 seems to break Rum HOT 3
- How to use daiquiri.core/html ? HOT 9
- How can I use npm based react library I rum ssr mode HOT 4
- Live Examples Missing HOT 1
- Hulunote(a tool for networked thought) use the rum😄
- Interpretation warnings print var symbol instead of the value
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rum.