File tree Expand file tree Collapse file tree 2 files changed +37
-2
lines changed
Expand file tree Collapse file tree 2 files changed +37
-2
lines changed Original file line number Diff line number Diff line change @@ -64,11 +64,15 @@ export default function useResizeObserver(
6464
6565 // Dynamic observe
6666 const isFuncTarget = typeof getTarget === 'function' ;
67+ const funcTargetIdRef = React . useRef ( 0 ) ;
68+
6769 React . useEffect ( ( ) => {
6870 const target = isFuncTarget ? getTarget ( ) : getTarget ;
6971
7072 if ( target && enabled ) {
7173 observe ( target , onInternalResize ) ;
74+ } else if ( enabled && isFuncTarget ) {
75+ funcTargetIdRef . current += 1 ;
7276 }
7377
7478 return ( ) => {
@@ -78,7 +82,8 @@ export default function useResizeObserver(
7882 } ;
7983 } , [
8084 enabled ,
81- // When is function, no need to watch it
82- isFuncTarget ? 0 : getTarget ,
85+ // If function target resolves after a parent render, the bumped ref value
86+ // lets the next render re-run this effect without watching the function identity.
87+ isFuncTarget ? funcTargetIdRef . current : getTarget ,
8388 ] ) ;
8489}
Original file line number Diff line number Diff line change 1+ import { render , waitFor } from '@testing-library/react' ;
2+ import { useEvent } from '@rc-component/util' ;
3+ import React from 'react' ;
4+ import { useResizeObserver } from '../src' ;
5+ import { _el as elementListeners } from '../src/utils/observerUtil' ;
6+
7+ describe ( 'useResizeObserver' , ( ) => {
8+ it ( 'should observe latest element when target getter closes over stateful ref value' , async ( ) => {
9+ function Demo ( ) {
10+ const [ element , setElement ] = React . useState < HTMLElement | null > ( null ) ;
11+ // `useEvent` keeps the getter identity stable while the closed-over DOM node
12+ // comes from state. If the hook only checks the function reference, it misses
13+ // the later state update from `null` to the actual element and never observes it.
14+ const getTarget = useEvent ( ( ) => element as HTMLElement ) ;
15+
16+ useResizeObserver ( true , getTarget ) ;
17+
18+ return < div ref = { setElement } data-testid = "target" /> ;
19+ }
20+
21+ const { getByTestId } = render ( < Demo /> ) ;
22+ const target = getByTestId ( 'target' ) ;
23+
24+ await waitFor ( ( ) => {
25+ // Once the ref callback stores the DOM into state, the latest element should
26+ // still be observed even though the getter function itself never changes.
27+ expect ( elementListeners . get ( target ) ) . toBeTruthy ( ) ;
28+ } ) ;
29+ } ) ;
30+ } ) ;
You can’t perform that action at this time.
0 commit comments