Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race condition on React 18 setState causes mouse to "skip" when dragging / resizing. #2003

Open
Noir-Lime opened this issue Dec 27, 2023 · 7 comments · May be fixed by #2043
Open

Race condition on React 18 setState causes mouse to "skip" when dragging / resizing. #2003

Noir-Lime opened this issue Dec 27, 2023 · 7 comments · May be fixed by #2043

Comments

@Noir-Lime
Copy link

Noir-Lime commented Dec 27, 2023

Describe the bug

So, After some thorough testing, I discovered that version 1.4.4 of this package has a bug where <GridItem/> elements "skip" when tracking the mouse if using React 18. I assume it's a race condition because it's performance dependent. Setting the performance throttling mode in Google Chrome dev tools affects how apparent the issue is. After digging through the source code, I found out this is because we are not wrapping any of the setState methods within ReactDom.flushSync().

It took a while for me to notice this, since my development machine is quite performant. It really became apparent when I was testing on a laptop.

Your Example Website or App

https://codesandbox.io/p/sandbox/romantic-frost-445xyf

Steps to Reproduce the Bug or Issue

  1. Go to provided code sandbox
  2. Ensure React 18 and react-grid-layout 1.4.4 are installed
  3. Go into index.js, make sure you are using createRoot() instead of ReactDOM.render() as the main React entry point.
  4. Go into chrome performance tab, set to either x4 or x6 slowdown.
  5. Try to drag or resize an element.

Expected behavior

I expected there to be no race condition, and that the element would be tracking the mouse's movements perfectly regardless of performance throttling.

react-grid-layout library version

1.4.4

Operating System Version

Linux Ubuntu 20

Browser

Chrome

Additional context

No response

Screenshots or Videos

romantic-frost-445xyf.-.CodeSandbox.-.Google.Chrome.2023-12-26.18-47-46.mp4
@benedict-jackson
Copy link

Looks like the solution to #1990

@AndreiAyar
Copy link

Switching react-draggable to 4.4.5 temporary seems to fix this.

@GuillaumeClementMontpellier
Copy link

I got it too, because in Chrome, the mousemove events are fired a lot more rapidly if the devTools is open.

Linked to react-draggable #699

What happens, react-draggable doesn't pass by setState for tracking updated (because React 18 batch state updates), but react-grid layout does, which means the deltaX / deltaY that is passed is from the last mouseEvent, not the last state update.

For correction, react-grid-layout should now also use object mutation instead of react state in order to correctly track position.

@soadzoor
Copy link

soadzoor commented Mar 21, 2024

Hey, any updates on this? I've spent 4 hours debugging my code, trying to figure out why my mouse is getting further and further away from the dragged object, then I narrowed it down to react, specifically if I change

const root = ReactDOM.createRoot(rootElement);

root.render(
	<App />
);

to
ReactDOM.render(<App/>, rootElement);

Then it's all good.

react-grid-layout-bug.mp4

The problem of course, is that we can't use ReactDOM.render in react 18 anymore. Should we downgrade to react 17, just because of this?

By the way, I had similar problems with drag and dropping three.js elements with my own code, especially when the dev tools was open. I also realized that the mousemove event is triggered much more frequently when dev tools are open in chrome.

My solution was pretty simple: keep track of the drag-start position of the mouse, and always check the latest coordinate of the mouse. This way it's kind of guaranteed that the dragged element will follow exactly the mouse. Even if there are minor errors frame by frame, they're not added up, because we only keep track of the first mouse position and the last one.

If anyone gets inspired by this, and creates a bugfix for this solution, I'd be eternally grateful.

@soadzoor
Copy link

As mentioned by someone in #1990 , downgrading this lib to 1.4.3 also solves this issue, so we can keep using react 18.

Not sure what exactly changed from 1.4.3 to 1.4.4 that affects this

@soadzoor
Copy link

for the record, today I started having the problems with 1.4.3 as well, so it's probably not a 100% solution

@ligoo
Copy link

ligoo commented Apr 11, 2024

someone found a way to make it work with React18? as ReactDOM.render is not available anymore and downgrading to 1.4.3 is having the same issue I can't see a temporary fix either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants