hey y’all, I noticed the “controlled input cursor bug” is present when using reagent 1.2.0 and react 18 for pretty vanilla input components with :type :email or :type :number , has anyone else run into this and do you have suggestions? from all my googling it looks like there’s known compatibility issues with reagent and react 18?
here’s a small repo to repro: https://github.com/flyingmachine/reagent-react-18-controlled-input
I think it is a problem that became worse with the react 18 batching (causing reagent “double batching”). If you look at the reagent impl, you can see that not all input types are handled. If you look in React codebase instead, you’ll see it does have special handling for all types (pretty sure I did this dig at one point). I don’t think there is any sort of surface-level controlled/uncontrolled trick that can fix it. It comes down to the underlying syncing/batching/flushing model.
email seems simple enough based on the html spec Mike linked, number can't be fixed with the workaround
appreciate the guidance 🙂 think i’m going to have to switch back to react 17 for the time being
Hmm, do those inputs really with react-17? 😮 Does it create the same DOM input element?
email does at least, i will double-check number
Just in case - does the "external/internal value atoms" trick not fix the cursor jumping?
email and number both work with react-17
sorry what’s the external/internal value atoms trick?
I pushed a react-17 branch to the repro repo https://github.com/flyingmachine/reagent-react-18-controlled-input/blob/react-17/src/main/app.cljs
Reagent workaround should be checking the node type property and if it is email or number it shouldn't use the workaround, so I wonder how it works on react 17
indeed thinking-face
@nonrecursive It's what at least re-com uses: https://github.com/day8/re-com/blob/master/src/re_com/input_text.cljs#L65
It basically creates a controlled wrapper around an uncontrolled input.
ooh interesting
(I thought it was also documented somewhere in Reagent repo, but can't find it.)
For MUI I've recommended the solution which enables using Reagent input workaround with MUI TextFields, I'm not sure if this alternative is documented
For MUI it is, yeah.
https://github.com/reagent-project/reagent/blob/master/doc/ControlledInputs.md The RN workaround here is somewhat similar
ah yes, I’ve come across that - I think the line highlighting in the workaround link might be out of date, made it hard to distinguish what the actual workaround was
What I like about the "internal/external model" approach is that it's applicable in any context. I've used it with MUI, with stateful nodes (`canvas`), with JS libraries that aren't aware of React.
Hmm, I don't see how internal/external model solves the cursor jumping, if the internal model is still a Reagent Atom. It doesn't at least fully avoid the Reagent rAF queue/batching. It might make the updates faster, local ratom update vs. handling Re-frame event and then app-db change triggering a subscription, but I don't think that is enough to avoid this.
I don't know the internals. The main thing is that the component is not re-rendered at all if the value is changed via the input itself. It's only re-rendered when the externally specified value is changed.
I opened Reagent demo site and I was able to both reproduce the problem with React 18 and see it works with React 17. On React 17 this condition isn't true so the workaround isn't used: https://github.com/reagent-project/reagent/blob/master/src/reagent/impl/input.cljs#L83 MAYBE due to React 18 batching (https://github.com/facebook/react/blob/main/CHANGELOG.md#react-2, => double batching because Reagent also has the rAF queue) the DOM value isn't yet updated when this event runs and Reagent workaround logic triggers, but it can't be used on email/number inputs due to them not having the Selection API.
I wonder if we could use React flushSync in the input workaround to avoid React event batching
that would be cool!
I didn't find any way it would work. Not sure, looks like our problem is somehow the other way around, not about making our updates reflected synchronously in the DOM, but seeing the updated DOM in the event handler. Not sure how that it possible. This does affect other input types also (text etc.) but the workaround code works for them as they have the Selection API.
Huh. Is the issue not there when you don't specify :type?
things work as expected when there’s no :type specified; the issue isn’t there
I created an issue and got some clarification: https://github.com/reagent-project/reagent/issues/609