Skip to content

Commit 77bdb90

Browse files
committed
[fix] Avoid needing to memoize onLayout callbacks
If 'onLayout' is an inline function, it could cause the DOM node to enter a cycle of being observed/unobserved with the result that 'onLayout' was constantly called. Fix #1704
1 parent 7fc17d0 commit 77bdb90

1 file changed

Lines changed: 16 additions & 7 deletions

File tree

packages/react-native-web/src/hooks/useElementLayout.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,32 @@ function getResizeObserver(): ?ResizeObserver {
6161

6262
export default function useElementLayout(
6363
ref: ElementRef<any>,
64-
onLayout?: (e: LayoutEvent) => void
64+
onLayout?: ?(e: LayoutEvent) => void
6565
) {
6666
const observer = getResizeObserver();
6767

6868
useLayoutEffect(() => {
6969
const node = ref.current;
70-
if (node != null && observer != null && typeof onLayout === 'function') {
71-
observer.observe(node);
72-
// $FlowFixMe
70+
if (node != null) {
7371
node[DOM_LAYOUT_HANDLER_NAME] = onLayout;
7472
}
73+
}, [ref, onLayout]);
74+
75+
// Observing is done in a separate effect to avoid this effect running
76+
// when 'onLayout' changes.
77+
useLayoutEffect(() => {
78+
const node = ref.current;
79+
if (node != null && observer != null) {
80+
if (typeof node[DOM_LAYOUT_HANDLER_NAME] === 'function') {
81+
observer.observe(node);
82+
} else {
83+
observer.unobserve(node);
84+
}
85+
}
7586
return () => {
7687
if (node != null && observer != null) {
7788
observer.unobserve(node);
78-
// $FlowFixMe
79-
delete node[DOM_LAYOUT_HANDLER_NAME];
8089
}
8190
};
82-
}, [ref, onLayout, observer]);
91+
}, [ref, observer]);
8392
}

0 commit comments

Comments
 (0)