Open yf-yang opened 1 month ago
I have run it but haven't encountered any issues with it.
Generally speaking, React 18 auto batching's mechanism of event handlers is like:
function domOnValueChange(e) {
reactComponentOnChange(e); // collect state updates but does not actually performs those updates, not an actual function name
performStateUpdates(); // here the auto batching works, not an actual function name
// some additional codes to maintain DOM node states
restoreControlledState(element, props); // actual function, use latest props value of the corresponding component to update element
}
The restoreControlledState
function will then deal with <input />
, <textarea />
and <select />
specifically. It will finally call three different functions called updateWrapper
that handles the DOM node.
Suppose this is an <input />
component, then when a character is typed, the DOM <input />
node will change, its value will add one character, and triggers the change event handler. After some state changes, it will finally call updateWrapper
.
Here, if the state is updated in the same micro task, then the props.value
property will be the same with current DOM node, so the cursor location will not be affected.
Instead, if the state update is postponed to another micro task, then props.value
remains unchanged (suppose it is 'second'), but the DOM node's value has already added one more character (suppose it is 'secaond'). Here React's updateWrapper
will reset the DOM node's value to the unchanged one ('secaond' -> 'second'). During the reset operation, the cursor location is lost. During the next micro task, although the state will finally be updated to the one with one more character ('secaond'), the cursor location is lost and would be moved to the last character.
I personally think this issue should be categorized as a wont fix, but maybe someone can offer a solution to make it more sound, I'm not sure.
NOTE: In latest React main branch some function name has changed, but their names are pretty similar and it is not difficult to find the corresponding logic.
React version: v18.3
Steps To Reproduce
Link to code example: https://codesandbox.io/p/sandbox/74mhkd
The current behavior
By adding an additional queueMicrotask to the second input, two inputs behavior are different.
https://github.com/user-attachments/assets/5cc7e2f6-0706-43ef-88cd-08177ab59a35
The expected behavior
Work loop stuff should not affect DOM manipulation.
Is it a bug or feature? Is it a react stuff?