Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TouchableOpacity componentDidUpdate causing an excessive number of pending callbacks #35387

Conversation

gabrieldonadel
Copy link
Collaborator

Summary

The commit 3eddc9a included on v0.69 introduced a wrong if statement inside the componentDidUpdate function of the TouchableOpacity component. As this if statement always evaluates to true ((true || false) !== undefined) we end up making unnecessary calls to the _opacityInactive method every time the component props changes, e.g. every time a <Text> inside the TouchableOpacity changes we call this function over and over, and this has been causing some performance issues on big lists.

This PR fixes this problem by adjusting the componentDidUpdate function to only call _opacityInactive when necessary.

Closes #34442
Closes #32476

Changelog

[General] [Fixed] - Fix TouchableOpacity componentDidUpdate causing an excessive number of pending callbacks

Test Plan

  1. Open the RNTester app and navigate to the Touchable* and onPress page
  2. Test the TouchableOpacity component through the many sections

@facebook-github-bot facebook-github-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 Nov 18, 2022
@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 7,102,178 -91
android hermes armeabi-v7a 6,470,253 -1,206
android hermes x86 7,519,683 +65
android hermes x86_64 7,378,336 +298
android jsc arm64-v8a 8,967,121 +0
android jsc armeabi-v7a 7,697,980 +5
android jsc x86 9,029,282 -4
android jsc x86_64 9,507,103 +4

Base commit: 4d7ddd4
Branch: main

@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
ios - universal n/a --

Base commit: 4d7ddd4
Branch: main

@pull-bot
Copy link

PR build artifact for d3f397c is ready.
To use, download tarball from "Artifacts" tab in this CircleCI job then run yarn add <path to tarball> in your React Native project.

@facebook-github-bot
Copy link
Contributor

@ryancat has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

@gabrieldonadel gabrieldonadel deleted the fix/touchable-opacity-component-did-update branch November 18, 2022 20:50
@benomatis
Copy link

@gabrieldonadel when is this supposed to go live? It's still not in 0.71.2, I still have to use a patch for it... has it been missed maybe and never merged?

@gabrieldonadel
Copy link
Collaborator Author

@benomatis based on the changelog below this will most likely be released on 0.72

- Fix TouchableOpacity componentDidUpdate causing an excessive number of pending callbacks ([8b1f6e09c1](https://github.com/facebook/react-native/commit/8b1f6e09c1b11e07096156d8d01aaff649745fbc) by [@gabrieldonadel](https://github.com/gabrieldonadel))

@benomatis
Copy link

thank you @gabrieldonadel

kelset pushed a commit that referenced this pull request Mar 6, 2023
…f pending callbacks (#35387)

Summary:
The commit 3eddc9a included on v0.69 introduced a wrong `if` statement inside the `componentDidUpdate` function of the `TouchableOpacity` component. As this `if` statement always evaluates to `true` (`(true || false) !== undefined`) we end up making unnecessary calls to the `_opacityInactive` method every time the component props changes, e.g. every time a `<Text>` inside the TouchableOpacity changes we call this function over and over, and this has been causing some performance issues on big lists.

This PR fixes this problem by adjusting the `componentDidUpdate` function to only call  `_opacityInactive` when necessary.

Closes #34442
Closes #32476

## Changelog

[General] [Fixed] - Fix TouchableOpacity componentDidUpdate causing an excessive number of pending callbacks

Pull Request resolved: #35387

Test Plan:
1. Open the RNTester app and navigate to the `Touchable* and onPress` page
2. Test the `TouchableOpacity` component through the many sections

Reviewed By: cipolleschi

Differential Revision: D41397396

Pulled By: ryancat

fbshipit-source-id: 24863b5cbbdd2f3dd1f654b43d7031560937b888
@fivecar
Copy link
Contributor

fivecar commented Mar 16, 2023

@benomatis : I just installed 0.71.4, and it seems to have the fix, FWIW. (Thanks, @gabrieldonadel, for fixing this. Spent a long time debugging my app until I saw this on the interwebs.)

@benomatis
Copy link

@fivecar Yes, I can confirm it's added to 0.71.4, thank you!

OlimpiaZurek pushed a commit to OlimpiaZurek/react-native that referenced this pull request May 22, 2023
…f pending callbacks (facebook#35387)

Summary:
The commit facebook@3eddc9a included on v0.69 introduced a wrong `if` statement inside the `componentDidUpdate` function of the `TouchableOpacity` component. As this `if` statement always evaluates to `true` (`(true || false) !== undefined`) we end up making unnecessary calls to the `_opacityInactive` method every time the component props changes, e.g. every time a `<Text>` inside the TouchableOpacity changes we call this function over and over, and this has been causing some performance issues on big lists.

This PR fixes this problem by adjusting the `componentDidUpdate` function to only call  `_opacityInactive` when necessary.

Closes facebook#34442
Closes facebook#32476

## Changelog

[General] [Fixed] - Fix TouchableOpacity componentDidUpdate causing an excessive number of pending callbacks

Pull Request resolved: facebook#35387

Test Plan:
1. Open the RNTester app and navigate to the `Touchable* and onPress` page
2. Test the `TouchableOpacity` component through the many sections

Reviewed By: cipolleschi

Differential Revision: D41397396

Pulled By: ryancat

fbshipit-source-id: 24863b5cbbdd2f3dd1f654b43d7031560937b888
@cipolleschi cipolleschi mentioned this pull request Oct 11, 2023
@VictorioMolina
Copy link

VictorioMolina commented Jul 15, 2024

I am experiencing some issues opening a transparent modal with the keyboard opened. Also, I am listening to keyboard updates with 'will' and not 'did'. If I only listen 'didShow/didHide' events, the error disappear.

Open keyboard -> Press TouchableOpacity button -> Open transparent modal -> Keyboard is implicitly dismissed (automatically) -> Close modal -> Keyboard is opened again automatically with buggy behaviour -> ERROR!

   <Modal
      transparent
      visible={visible}
      animationType="fade"
      onRequestClose={onClose}
    >
      <View style={containerStyle}>
        {renderBlur()}
        {renderMain()}
        {renderCloseButton()}
      </View>
    </Modal>

This is the error I am getting:

Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"1506":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1509":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1512":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1515":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1518":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1521":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1524":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1527":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1530":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1533":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1536":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1539":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1542":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1545":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1548":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1551":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1554":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1557":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1560":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1563":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1566":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1569":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1572":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1575":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1578":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1581":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1584":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1587":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1590":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1593":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1596":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1599":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1602":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1605":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1608":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1611":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1614":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1617":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1620":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1623":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1626":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1629":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1632":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1635":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1638":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1641":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1644":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1647":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1650":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1653":{"module":"UIManager","method":"configureNextLayoutAnimation"},"...(truncated keys)...":451}

As a workaround, I am replacing the TouchableOpacity with the one provided by react native gesture handler.

Any ideas?

@darboleda-paycargo
Copy link

I am experiencing some issues opening a transparent modal with the keyboard opened. Also, I am listening to keyboard updates with 'will' and not 'did'. If I only listen 'didShow/didHide' events, the error disappear.

Open keyboard -> Press TouchableOpacity button -> Open transparent modal -> Keyboard is implicitly dismissed (automatically) -> Close modal -> Keyboard is opened again automatically with buggy behaviour -> ERROR!

   <Modal
      transparent
      visible={visible}
      animationType="fade"
      onRequestClose={onClose}
    >
      <View style={containerStyle}>
        {renderBlur()}
        {renderMain()}
        {renderCloseButton()}
      </View>
    </Modal>

This is the error I am getting:

Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"1506":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1509":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1512":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1515":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1518":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1521":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1524":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1527":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1530":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1533":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1536":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1539":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1542":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1545":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1548":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1551":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1554":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1557":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1560":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1563":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1566":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1569":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1572":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1575":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1578":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1581":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1584":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1587":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1590":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1593":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1596":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1599":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1602":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1605":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1608":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1611":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1614":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1617":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1620":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1623":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1626":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1629":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1632":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1635":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1638":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1641":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1644":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1647":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1650":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1653":{"module":"UIManager","method":"configureNextLayoutAnimation"},"...(truncated keys)...":451}

As a workaround, I am replacing the TouchableOpacity with the one provided by react native gesture handler.

Any ideas?

hey Victorio, have you found a solution? I'm running into this same exact error

@darboleda-paycargo
Copy link

I am experiencing some issues opening a transparent modal with the keyboard opened. Also, I am listening to keyboard updates with 'will' and not 'did'. If I only listen 'didShow/didHide' events, the error disappear.
Open keyboard -> Press TouchableOpacity button -> Open transparent modal -> Keyboard is implicitly dismissed (automatically) -> Close modal -> Keyboard is opened again automatically with buggy behaviour -> ERROR!

   <Modal
      transparent
      visible={visible}
      animationType="fade"
      onRequestClose={onClose}
    >
      <View style={containerStyle}>
        {renderBlur()}
        {renderMain()}
        {renderCloseButton()}
      </View>
    </Modal>

This is the error I am getting:

Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"1506":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1509":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1512":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1515":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1518":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1521":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1524":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1527":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1530":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1533":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1536":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1539":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1542":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1545":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1548":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1551":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1554":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1557":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1560":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1563":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1566":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1569":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1572":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1575":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1578":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1581":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1584":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1587":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1590":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1593":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1596":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1599":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1602":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1605":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1608":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1611":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1614":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1617":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1620":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1623":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1626":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1629":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1632":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1635":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1638":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1641":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1644":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1647":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1650":{"module":"UIManager","method":"configureNextLayoutAnimation"},"1653":{"module":"UIManager","method":"configureNextLayoutAnimation"},"...(truncated keys)...":451}

As a workaround, I am replacing the TouchableOpacity with the one provided by react native gesture handler.
Any ideas?

hey Victorio, have you found a solution? I'm running into this same exact error

Temporary fix for me was to remove 'KeyboardAvoidingView' , as issue was only on iOS with this component

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.
Projects
None yet
8 participants