Skip to content

Commit 108e344

Browse files
author
Nik
authored
Fix react18 concurrent mode drag glitch due to state inconsistency (#699)
* Fix react18 concurrent mode drag glitch due to state inconsistency * Fix react18 concurrent mode drag glitch, eliminate DraggableCore.state
1 parent b788bad commit 108e344

File tree

2 files changed

+28
-42
lines changed

2 files changed

+28
-42
lines changed

lib/DraggableCore.js

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ const eventsFor = {
2828
// Default to mouse events.
2929
let dragEventFor = eventsFor.mouse;
3030

31-
type DraggableCoreState = {
32-
dragging: boolean,
33-
lastX: number,
34-
lastY: number,
35-
touchIdentifier: ?number
36-
};
37-
3831
export type DraggableData = {
3932
node: HTMLElement,
4033
x: number, y: number,
@@ -75,7 +68,7 @@ export type DraggableCoreProps = {
7568
// work well with libraries that require more control over the element.
7669
//
7770

78-
export default class DraggableCore extends React.Component<DraggableCoreProps, DraggableCoreState> {
71+
export default class DraggableCore extends React.Component<DraggableCoreProps> {
7972

8073
static displayName: ?string = 'DraggableCore';
8174

@@ -227,12 +220,13 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
227220
scale: 1,
228221
};
229222

230-
state: DraggableCoreState = {
231-
dragging: false,
232-
// Used while dragging to determine deltas.
233-
lastX: NaN, lastY: NaN,
234-
touchIdentifier: null
235-
};
223+
dragging: boolean = false;
224+
225+
// Used while dragging to determine deltas.
226+
lastX: number = NaN;
227+
lastY: number = NaN;
228+
229+
touchIdentifier: ?number = null;
236230

237231
mounted: boolean = false;
238232

@@ -298,7 +292,7 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
298292
// distinguish between individual touches on multitouch screens by identifying which
299293
// touchpoint was set to this element.
300294
const touchIdentifier = getTouchIdentifier(e);
301-
this.setState({touchIdentifier});
295+
this.touchIdentifier = touchIdentifier;
302296

303297
// Get the current drag point from the event. This is used as the offset.
304298
const position = getControlPosition(e, touchIdentifier, this);
@@ -322,12 +316,9 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
322316
// Initiate dragging. Set the current x and y as offsets
323317
// so we know how much we've moved during the drag. This allows us
324318
// to drag elements around even if they have been moved, without issue.
325-
this.setState({
326-
dragging: true,
327-
328-
lastX: x,
329-
lastY: y
330-
});
319+
this.dragging = true;
320+
this.lastX = x;
321+
this.lastY = y;
331322

332323
// Add events to the document directly so we catch when the user's mouse/touch moves outside of
333324
// this element. We use different events depending on whether or not we have detected that this
@@ -339,16 +330,16 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
339330
handleDrag: EventHandler<MouseTouchEvent> = (e) => {
340331

341332
// Get the current drag point from the event. This is used as the offset.
342-
const position = getControlPosition(e, this.state.touchIdentifier, this);
333+
const position = getControlPosition(e, this.touchIdentifier, this);
343334
if (position == null) return;
344335
let {x, y} = position;
345336

346337
// Snap to grid if prop has been provided
347338
if (Array.isArray(this.props.grid)) {
348-
let deltaX = x - this.state.lastX, deltaY = y - this.state.lastY;
339+
let deltaX = x - this.lastX, deltaY = y - this.lastY;
349340
[deltaX, deltaY] = snapToGrid(this.props.grid, deltaX, deltaY);
350341
if (!deltaX && !deltaY) return; // skip useless drag
351-
x = this.state.lastX + deltaX, y = this.state.lastY + deltaY;
342+
x = this.lastX + deltaX, y = this.lastY + deltaY;
352343
}
353344

354345
const coreEvent = createCoreData(this, x, y);
@@ -372,25 +363,23 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
372363
return;
373364
}
374365

375-
this.setState({
376-
lastX: x,
377-
lastY: y
378-
});
366+
this.lastX = x;
367+
this.lastY = y;
379368
};
380369

381370
handleDragStop: EventHandler<MouseTouchEvent> = (e) => {
382-
if (!this.state.dragging) return;
371+
if (!this.dragging) return;
383372

384-
const position = getControlPosition(e, this.state.touchIdentifier, this);
373+
const position = getControlPosition(e, this.touchIdentifier, this);
385374
if (position == null) return;
386375
let {x, y} = position;
387376

388377
// Snap to grid if prop has been provided
389378
if (Array.isArray(this.props.grid)) {
390-
let deltaX = x - this.state.lastX || 0;
391-
let deltaY = y - this.state.lastY || 0;
379+
let deltaX = x - this.lastX || 0;
380+
let deltaY = y - this.lastY || 0;
392381
[deltaX, deltaY] = snapToGrid(this.props.grid, deltaX, deltaY);
393-
x = this.state.lastX + deltaX, y = this.state.lastY + deltaY;
382+
x = this.lastX + deltaX, y = this.lastY + deltaY;
394383
}
395384

396385
const coreEvent = createCoreData(this, x, y);
@@ -408,11 +397,9 @@ export default class DraggableCore extends React.Component<DraggableCoreProps, D
408397
log('DraggableCore: handleDragStop: %j', coreEvent);
409398

410399
// Reset the el.
411-
this.setState({
412-
dragging: false,
413-
lastX: NaN,
414-
lastY: NaN
415-
});
400+
this.dragging = false;
401+
this.lastX = NaN;
402+
this.lastY = NaN;
416403

417404
if (thisNode) {
418405
// Remove event handlers

lib/utils/positionFns.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ export function getControlPosition(e: MouseTouchEvent, touchIdentifier: ?number,
7878

7979
// Create an data object exposed by <DraggableCore>'s events
8080
export function createCoreData(draggable: DraggableCore, x: number, y: number): DraggableData {
81-
const state = draggable.state;
82-
const isStart = !isNum(state.lastX);
81+
const isStart = !isNum(draggable.lastX);
8382
const node = findDOMNode(draggable);
8483

8584
if (isStart) {
@@ -94,8 +93,8 @@ export function createCoreData(draggable: DraggableCore, x: number, y: number):
9493
// Otherwise calculate proper values.
9594
return {
9695
node,
97-
deltaX: x - state.lastX, deltaY: y - state.lastY,
98-
lastX: state.lastX, lastY: state.lastY,
96+
deltaX: x - draggable.lastX, deltaY: y - draggable.lastY,
97+
lastX: draggable.lastX, lastY: draggable.lastY,
9998
x, y,
10099
};
101100
}

0 commit comments

Comments
 (0)