diff --git a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js index 0064e996238a..3c90587135e6 100644 --- a/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js +++ b/packages/react-native/Libraries/Components/Touchable/TouchableHighlight.js @@ -304,6 +304,12 @@ class TouchableHighlightImpl extends React.Component< render(): React.Node { const child = React.Children.only<$FlowFixMe>(this.props.children); + if (__DEV__ && child.type === React.Fragment) { + console.error( + 'TouchableHighlight does not support React.Fragment as a child. ' + + 'Wrap the children in a single host element such as .', + ); + } // BACKWARD-COMPATIBILITY: Focus and blur events were never supported before // adopting `Pressability`, so preserve that behavior. @@ -376,12 +382,14 @@ class TouchableHighlightImpl extends React.Component< testID={this.props.testID} ref={this.props.hostRef} {...eventHandlersWithoutBlurAndFocus}> - {cloneElement(child, { - style: StyleSheet.compose( - child.props.style, - this.state.extraStyles?.child, - ), - })} + {child.type === React.Fragment + ? child + : cloneElement(child, { + style: StyleSheet.compose( + child.props.style, + this.state.extraStyles?.child, + ), + })} {__DEV__ ? ( ) : null} diff --git a/packages/react-native/Libraries/Components/Touchable/__tests__/TouchableHighlight-itest.js b/packages/react-native/Libraries/Components/Touchable/__tests__/TouchableHighlight-itest.js index 715603bb6583..2ba6b8c370f9 100644 --- a/packages/react-native/Libraries/Components/Touchable/__tests__/TouchableHighlight-itest.js +++ b/packages/react-native/Libraries/Components/Touchable/__tests__/TouchableHighlight-itest.js @@ -395,6 +395,48 @@ describe('', () => { , ); }); + + // Regression test for #54933: a `React.Fragment` cannot accept the + // underlay style applied via `cloneElement`, so the highlight effect + // is silently broken. Render the Fragment unchanged and surface an + // actionable dev error pointing the user at wrapping in . + it('logs a dev error when given a React.Fragment as a child', () => { + const originalConsoleError = console.error; + const mockConsoleError = jest.fn(); + // $FlowFixMe[cannot-write] + console.error = mockConsoleError; + + try { + const root = Fantom.createRoot(); + + Fantom.runTask(() => { + root.render( + + + First + Second + + , + ); + }); + + expect( + root.getRenderedOutput({props: ['accessible']}).toJSX(), + ).toEqual( + + First + Second + , + ); + expect(mockConsoleError).toHaveBeenCalledTimes(1); + expect(mockConsoleError.mock.calls[0][0]).toContain( + 'TouchableHighlight does not support React.Fragment as a child', + ); + } finally { + // $FlowFixMe[cannot-write] + console.error = originalConsoleError; + } + }); }); });