react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

fix: `skipExiting` not working on Android

Open MatiPl01 opened this issue 6 months ago • 1 comments

Summary

Issue description

For some reason, componentWillUnmount was called too late on android and the ShadowNode removal mutation triggered the exiting layout animation before the componentWillUnmount was called. Since we used componentWillUnmount to disable exiting animations for LayoutAnimationConfigs on which the skipExiting prop was used, the disabled flag was set in CPP layout animations config object after the exiting animation started.

How it was fixed?

The fix is not perfect, but I think that it is sufficient, at least for most cases, because people don't usually modify skipExiting prop at all.

Instead of waiting until the component unmounts, I mark exiting animations as disabled just after the component mounts (only if skipExiting is set to true) and then update it every time that the skipExiting value changes. In most cases it doesn't change at all, so in effect I set the skipExiting value in CPP only once.

Example recordings

Before After

Test plan

Copy this code and paste to the EmptyExample to see how it works.

Code snippet
import { useEffect, useState } from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
  FadeOut,
  LayoutAnimationConfig,
} from 'react-native-reanimated';

export default function App() {
  const [show, setShow] = useState(true);

  useEffect(() => {
    setTimeout(() => {
      setShow(false);
    }, 1000);
  }, []);

  return (
    show && (
      <LayoutAnimationConfig skipEntering skipExiting>
        <Animated.View exiting={FadeOut} style={styles.box} />
      </LayoutAnimationConfig>
    )
  );
}

const styles = StyleSheet.create({
  box: {
    width: 200,
    height: 200,
    backgroundColor: 'red',
  },
});

MatiPl01 avatar Jun 23 '25 15:06 MatiPl01

After consulting with @bartlomiejbloniarz, it turned out that this approach also breaks this case when the exiting animation should be triggered:

<LayoutAnimationConfig skipEntering skipExiting>
  {show && <Animated.View exiting={FadeOut} style={styles.box} />}
</LayoutAnimationConfig>

I will have to work on a different solution then.

MatiPl01 avatar Jun 24 '25 14:06 MatiPl01

Closed as RN 0.82 fixes the issue

MatiPl01 avatar Sep 09 '25 11:09 MatiPl01