Code change:
<!-- Note: if the issue is about documentation or the website, please file it at: --Do you want to request a feature or report a bug? Bug What is the current behavior? when typing in a controlled input, the cursor always jumps to the end. This was an old issue that seems to have resurfaced. used in the docs has the problem in all browsers as far as I have been able to test. What is the expected behavior? because we are using the state to update the component as soon as it's changed, the input element should be able to keep the cursor in the same place. Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React? I'm at latest (16.8.2) and I tested on Chrome, FireFox, and Edge on Windows as far as I know, this was working at some point, though I don't know how long ago. possibly even before "Fiber"
This is quite weird. Same code works for me on CodeSandbox: Not sure what's going on here.
Seems UMD-specific.
Thank you very much for reporting this. It's a serious regression in the last patch release, and exposed some lacking coverage in our test suite regarding UMD bundles. I have a fix ready in
Great! thank you for the fix.
This is fixed in 16.8.3. Unfortunately unpkg doesn't seem to pick up the 16.8.3 version yet from its default redirect.
That's OK, I replaced the resources with the specific release artifacts to test and it works great now.
it flipped for me and I'm actually having the same problem OP reported in your CodeSandbox, but not in his codepen. Should that be? Chrome 74
I've updated from react 16.8.1 to 16.8.6. Still having the same problem...
I am running into this same issue. I have created the following fiddle which is a boiled down version of what I have. Ultimately once the event stack finishes it appears that React clears the value in the input since it is controlled. Then when the timeout fires it sets the correct value but at this time the position is lost. I tried the fix this by handling the state internally to the TestInput Component as in the following fiddle. But after debugging it appears that setState causes getDerivedStateFromProps to be called which has the old value and I end up in the same mess. I feel I need getDerivedStateFromProps because I have handle the case where the value can change externally and I need to set the state to this new value. I believe if getDerivedStateFromProps was NOT called for a setState change then perhaps this problem would not exist, at least for my second example. But I am not familiar with the internals of React to even feel confident in this suggestion, so please take it with a grain of salt of course.
Okay based on my second fiddle I have come up with the following solution which should not require weird cursor manipulation. Please review, test, and use at your discretion. I have tested it a little and it appears to work. If I run into any problems I will post here.
Is this issue fixed? I'm having the same problem in 16.8.6.
Here is how I reproduce this issue. Is there something I'm doing wrong (or should do differently)?
There are 2 possible ways to get around this issue, as far as I can tell. Solution 1: Use the from the prop. Solution 2: Update the local state simultaneously as the parent state.
You're round-tripping the value change from to and back to and then calling . Apparently this round-trip makes React forget/reset the cursor position because I assume it looses a association between value and input element and/or re-renders the whole component. suggested in to call directly in the component which does work, but is not ideal when one prefers a stateless component. What I've done to workaround is to make the uncontrolled (change to ) with a prop. This also brings the benefit of the input remaining responsive when is computationally expensive.
In your example if you make a change, the InputChild component will be rendered once with outdated values. This is because the new value isn't set until useEffect. So whatever you typed will be erased for one frame, then put back after useEffect. This is enough to make the cursor position ambiguous to the browser. As a hack suggestion, you can swap useEffect with useMemo. This works because useMemo runs before render.

Related discussion:
text: unstable_continueExecution, unstable_wrapCallback, unstable_getCurrentPriorityLevel, <ins> unstable_IdlePriority, unstable_ImmediatePriority, unstable_LowPriority, unstable_NormalPriority, unstable_UserBlockingPriority, </ins> } from 'scheduler'; import { __interactionsRef,