Giter Club home page Giter Club logo

Comments (4)

tonsky avatar tonsky commented on July 19, 2024 2

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 and preventDefault, avoiding React and later layers

from rum.

robinchew avatar robinchew commented on July 19, 2024

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.

roman01la avatar roman01la commented on July 19, 2024

@robinchew Please try to repro this in 0.12.0-SNAPSHOT and report any issues to #205

from rum.

roman01la avatar roman01la commented on July 19, 2024

0.12.0 has been released

from rum.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.