@@ -306,5 +306,102 @@ describe('render Resizable', () => {
306306 } ) ;
307307 } ) ;
308308 } ) ;
309+
310+ describe ( 'onResizeStop with stale props' , ( ) => {
311+ // This tests the fix for a bug where onResizeStop would report stale size data
312+ // because React's batched state updates mean props.width/height haven't updated yet
313+ // when onResizeStop fires. The fix stores the last size from onResize and uses it
314+ // in onResizeStop. See: https://github.com/react-grid-layout/react-grid-layout/pull/2224
315+
316+ test ( 'onResizeStop reports correct size even when props are stale' , ( ) => {
317+ // Create a fresh element with fresh mocks for this test
318+ const onResizeStop = jest . fn ( ) ;
319+ const onResize = jest . fn ( ) ;
320+ const testProps = {
321+ ...customProps ,
322+ onResize,
323+ onResizeStop,
324+ } ;
325+ const element = shallow ( < Resizable { ...testProps } > { resizableBoxChildren } </ Resizable > ) ;
326+ const seHandle = findHandle ( element , 'se' ) ;
327+
328+ // Simulate onResizeStart
329+ seHandle . prop ( 'onStart' ) ( mockEvent , { node, deltaX : 0 , deltaY : 0 } ) ;
330+
331+ // Simulate dragging - this calls onResize with the new size
332+ seHandle . prop ( 'onDrag' ) ( mockEvent , { node, deltaX : 20 , deltaY : 30 } ) ;
333+ expect ( onResize ) . toHaveBeenLastCalledWith (
334+ mockEvent ,
335+ expect . objectContaining ( {
336+ size : { width : 70 , height : 80 } ,
337+ } )
338+ ) ;
339+
340+ // Now simulate onResizeStop. In a real app, React may not have re-rendered yet,
341+ // so props.width/height would still be 50. The deltaX/deltaY from DraggableCore's
342+ // onStop is typically 0 or very small since the mouse hasn't moved since the last
343+ // drag event. Without the fix, this would incorrectly report size: {width: 50, height: 50}.
344+ seHandle . prop ( 'onStop' ) ( mockEvent , { node, deltaX : 0 , deltaY : 0 } ) ;
345+
346+ // With the fix, onResizeStop should report the same size as the last onResize
347+ expect ( onResizeStop ) . toHaveBeenCalledWith (
348+ mockEvent ,
349+ expect . objectContaining ( {
350+ size : { width : 70 , height : 80 } ,
351+ } )
352+ ) ;
353+ } ) ;
354+
355+ test ( 'onResizeStop reports correct size for west handle with stale props' , ( ) => {
356+ const onResizeStop = jest . fn ( ) ;
357+ const onResize = jest . fn ( ) ;
358+ const testProps = {
359+ ...customProps ,
360+ onResize,
361+ onResizeStop,
362+ } ;
363+ const testMockClientRect = { left : 0 , top : 0 } ;
364+ const testNode = document . createElement ( 'div' ) ;
365+ // $FlowIgnore
366+ testNode . getBoundingClientRect = ( ) => ( { ...testMockClientRect } ) ;
367+
368+ const element = shallow ( < Resizable { ...testProps } > { resizableBoxChildren } </ Resizable > ) ;
369+ const wHandle = findHandle ( element , 'w' ) ;
370+
371+ // Simulate onResizeStart - this sets lastHandleRect to {left: 0, top: 0}
372+ wHandle . prop ( 'onStart' ) ( mockEvent , { node : testNode , deltaX : 0 , deltaY : 0 } ) ;
373+
374+ // Simulate dragging west (left)
375+ // deltaX = -15 from drag, plus position adjustment of -15 (handle moved from 0 to -15)
376+ // Total deltaX = -30, reversed for 'w' = +30, so width = 50 + 30 = 80
377+ testMockClientRect . left = - 15 ;
378+ wHandle . prop ( 'onDrag' ) ( mockEvent , { node : testNode , deltaX : - 15 , deltaY : 0 } ) ;
379+ expect ( onResize ) . toHaveBeenLastCalledWith (
380+ mockEvent ,
381+ expect . objectContaining ( {
382+ size : { width : 80 , height : 50 } ,
383+ } )
384+ ) ;
385+
386+ // Continue dragging - element moves further left
387+ testMockClientRect . left = - 25 ;
388+ wHandle . prop ( 'onDrag' ) ( mockEvent , { node : testNode , deltaX : - 10 , deltaY : 0 } ) ;
389+ expect ( onResize ) . toHaveBeenLastCalledWith (
390+ mockEvent ,
391+ expect . objectContaining ( {
392+ size : { width : 100 , height : 50 } ,
393+ } )
394+ ) ;
395+
396+ // onResizeStop with stale props - should use stored lastSize
397+ wHandle . prop ( 'onStop' ) ( mockEvent , { node : testNode , deltaX : 0 , deltaY : 0 } ) ;
398+ expect ( onResizeStop ) . toHaveBeenCalledWith (
399+ mockEvent ,
400+ expect . objectContaining ( {
401+ size : { width : 100 , height : 50 } ,
402+ } )
403+ ) ;
404+ } ) ;
405+ } ) ;
309406 } ) ;
310407} ) ;
0 commit comments