Skip to content

Commit 2e36e63

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Add Fantom test verifying onLayout does not bubble to ancestors (#57444)
Summary: Pull Request resolved: #57444 `onLayout` is a direct (non-bubbling) event, so a layout event fired on a child should not invoke an ancestor's `onLayout` prop handler. Add a Fantom integration test that renders a parent and child `<View>`, both with `onLayout`, then dispatches a layout event on the child and asserts the parent's `onLayout` prop is not called as a result. The initial layout pass emits a real layout event for every view that has `onLayout`, and those events are flushed lazily on the first dispatched event. The test flushes them up front and snapshots the call counts before dispatching, so the parent's own mount-time layout event is not mistaken for bubbling. Changelog: [Internal] Reviewed By: javache Differential Revision: D110755346 fbshipit-source-id: ac9fa907ac623427192ed81dbfb2d8e55d8bc500
1 parent af3a651 commit 2e36e63

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

packages/react-native/src/private/renderer/core/__tests__/EventTargetDispatching-itest.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,5 +1582,49 @@ const {isOSS} = Fantom.getConstants();
15821582
expect(parentSpy).toHaveBeenCalledTimes(1);
15831583
});
15841584
});
1585+
1586+
describe('direct events (onLayout)', () => {
1587+
it('does not bubble onLayout to ancestor views via the onLayout prop', () => {
1588+
const root = Fantom.createRoot();
1589+
1590+
const childRef = React.createRef<React.ElementRef<typeof View>>();
1591+
1592+
const parentSpy = jest.fn();
1593+
const childSpy = jest.fn();
1594+
1595+
Fantom.runTask(() => {
1596+
root.render(
1597+
<View onLayout={parentSpy}>
1598+
<View ref={childRef} onLayout={childSpy} />
1599+
</View>,
1600+
);
1601+
});
1602+
1603+
// Flush the layout events emitted for both views during the initial
1604+
// layout pass so they are not conflated with the dispatch below.
1605+
Fantom.flushAllNativeEvents();
1606+
1607+
// Both onLayout handlers fired for their own layout during mount.
1608+
const childCallsBefore = childSpy.mock.calls.length;
1609+
const parentCallsBefore = parentSpy.mock.calls.length;
1610+
1611+
Fantom.dispatchNativeEvent(
1612+
childRef,
1613+
'onLayout',
1614+
{layout: {x: 0, y: 0, width: 100, height: 50}},
1615+
{
1616+
category: Fantom.NativeEventCategory.Discrete,
1617+
},
1618+
);
1619+
1620+
// Child's onLayout handler fires for the dispatched event
1621+
expect(childSpy.mock.calls.length - childCallsBefore).toBeGreaterThan(
1622+
0,
1623+
);
1624+
// Parent's onLayout prop handler does NOT fire from the child's event
1625+
// because layout is a direct (non-bubbling) event
1626+
expect(parentSpy.mock.calls.length - parentCallsBefore).toBe(0);
1627+
});
1628+
});
15851629
},
15861630
);

0 commit comments

Comments
 (0)