Skip to content

Leave a view untransformed on iOS when its transform is not finite - #59133

Open
YevheniiKotyrlo wants to merge 1 commit into
react:mainfrom
YevheniiKotyrlo:fix/ios-non-finite-transform
Open

YevheniiKotyrlo wants to merge 1 commit into
react:mainfrom
YevheniiKotyrlo:fix/ios-non-finite-transform

Conversation

@YevheniiKotyrlo

@YevheniiKotyrlo YevheniiKotyrlo commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary:

A view whose transform holds a NaN disappears on iOS, together with the siblings drawn before it. On Android the same view renders untransformed and its siblings are unaffected. I hit it through Reanimated, whose withTiming computes a NaN for an undefined duration, but any transform computed as NaN does it.

RCTCATransform3DFromTransformMatrix copies the resolved matrix into a CATransform3D unchecked, so the NaN reaches Core Animation. Android's BaseViewManager reads each transform value through sanitizeFloatPropertyValue first, and on iOS updateLayoutMetrics already skips a non-finite frame because a CALayer cannot take one.

RCTCATransform3DFromTransformMatrix now returns the identity for a matrix with a non-finite entry, so RCTViewComponentView and the synchronous update in RCTMountingManager render the view untransformed, as Android does.

Changelog:

[IOS] [FIXED] - Render a view untransformed when its transform is not finite, instead of hiding it and the siblings drawn before it

Test Plan:

  • RCTViewComponentViewTests gains three cases that set a transform through updateProps: a translate with NaN and a scale with infinity leave the layer's transform at the identity, and a finite translate is applied. I ran React-RCTFabric's test spec on an iPad (iOS 27.0.1), with the spec enabled in RNTester's Podfile locally: all 22 RCTViewComponentViewTests pass with this change, and with main's RCTConversions.h the NaN and infinity cases fail. The spec's one other failure, RCTTextInputUtilsTest testCopyBackedTextInputPreservesTintColor, fails the same way on main on that device.
  • RNTester release builds of main and of this change on the same iPad, with a root component that renders a build label, a button, a view whose translateX becomes NaN after mount, and a second view. On main only the second view is drawn: the label, the button and the NaN view are gone. With this change all four are drawn and the NaN view sits untransformed. The before and after are in a comment below.
  • clang-format 21.1.2 passes on both files.

@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor Author

Device evidence — before / after

UNFIXED — the label, the button and the view whose translateX becomes NaN are not drawn; only the view after them is.

FIXED — all four are drawn, and the NaN view sits where layout puts it, untransformed.

before — main at e04aaf62f7 after — with this PR

iPad Pro 12.9-inch (4th generation), iOS 27.0.1: RNTester release builds of main at e04aaf62f7 and of this PR at 7ef7a7ad3a, one session, with the scene below as the root component and a label naming the build. In the full frames the NaN view's steelblue covers 0 pixels on main and 102,400 with this change (its 320 × 320 px), the button title's blue 0 and 2,565, and the second view's orange 102,400 in both.

Scene
function NonFiniteTransformExample() {
  const [translateX, setTranslateX] = React.useState(0);
  React.useEffect(() => {
    setTranslateX(NaN);
  }, []);
  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.label}>{BUILD}</Text>
      <Button title="Button before the NaN view" onPress={() => {}} />
      <View style={[styles.box, styles.subject, {transform: [{translateX}]}]} />
      <View style={[styles.box, styles.control]} />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {flex: 1, padding: 24, gap: 24, backgroundColor: 'white'},
  label: {fontSize: 14, color: 'black'},
  box: {width: 160, height: 160},
  subject: {backgroundColor: 'rgb(70, 130, 180)'},
  control: {backgroundColor: 'rgb(255, 140, 0)'},
});

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 16, 2026
@YevheniiKotyrlo
YevheniiKotyrlo marked this pull request as ready for review October 16, 2026 12:36
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 16, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant