0

I am trying to have some components fade in and out on mount and unmount using react-native-reanimated. I think the code is pretty simple:

import { View } from "react-native";
import Animated, { FadeIn, FadeOut } from "react-native-reanimated";

export const Dialog = () => (
  <Animated.View
    style={styles.loadingWrapper}
    entering={FadeIn}
    exiting={FadeOut}
  >
    <Progress.CircleSnail />
  </Animated.View>
);

const App = () => {

  const [isVisible, setIsVisible] = useState(false);

  return (
    <View>
      {isVisible && <Dialog />}
      <Button 
        title="Open Dialog" 
        onPress={() => setIsVisible(true)}
      />
    </View>
  );

}

My expectation here is that as the isVisible prop changes, the Dialog would fade in and out of existinence. What is happening is that it is popping in and out of existence, as if I were using a simple View, not an Animated.View.

Snack demonstrating the setup

I am unable to reproduce this issue in a snack. In the snack it seems to work fine. In my actual codebase, which is just a slightly more layered version of this, there is no animation. How might I be able to even begin debugging this?

This is the case for all instances of Animated.View in my app. I had it working at some point, and then somewhere along the way, it stopped working. I'm not sure what changed. I am using an expo managed project. Here's the relevant parts of my package.json and versions:

{
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "@expo/webpack-config": "~0.16.2",
    "@gorhom/bottom-sheet": "^4.3.1",
    "@react-native-async-storage/async-storage": "~1.17.6",
    "@react-navigation/bottom-tabs": "^6.3.1",
    "@react-navigation/drawer": "^6.4.1",
    "@react-navigation/native": "^6.0.10",
    "@react-navigation/native-stack": "^6.6.2",
    "expo": "^45.0.4",
    "expo-web-browser": "^10.2.1",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-native": "0.68.2",
    "react-native-dropdown-picker": "^5.4.2",
    "react-native-gesture-handler": "~2.2.1",
    "react-native-get-random-values": "~1.8.0",
    "react-native-maps": "0.30.2",
    "react-native-progress": "^5.0.0",
    "react-native-reanimated": "~2.8.0",
    "react-native-safe-area-context": "4.2.4",
    "react-native-screens": "~3.11.1",
    "react-native-svg": "12.3.0",
    "react-native-web": "0.17.7",
    "webpack-dev-server": "~3.11.0"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@types/react": "~17.0.21",
    "@types/react-native": "~0.67.7",
    "babel-plugin-inline-import": "^3.0.0",
    "react-devtools": "^4.24.7",
    "typescript": "~4.3.5"
  },
}

And my babel config, as recommended by the install docs for react-native-reanimated:

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    plugins: [
      [
        "babel-plugin-inline-import",
        {
          extensions: [".svg"],
        },
      ],
      "react-native-reanimated/plugin",
    ],
  };
};

Other libraries which rely on react-native-reanimated, like react-native-navigation, or react-native-bottomsheet, seem to be animating just fine. Am I doing something wrong? Did my packages get mismatched somewhere along the way and my animations stopped working all of a sudden?

Seth Lutske
  • 9,154
  • 5
  • 29
  • 78
  • Check out [this](https://snack.expo.dev/@kartikeyvaish/fadeinout-indicator) Snack. – Kartikey Jun 15 '22 at 04:44
  • @Kartikey that snack is not terribly helpful. Yes, it is a working example of what I am trying to acheive. But I don't see any difference between what you have there, and what I have in my code. Am I missing something? What is wrong with *my* code that its not working like yours? – Seth Lutske Jun 15 '22 at 15:12
  • @Kartikey I edited my question to include a living example of the issue. Perhaps you can take a look and see why my code may be different enough to not work the same as yours. – Seth Lutske Jun 15 '22 at 16:14
  • Hey Seth, you forgot to add `entering` and `exiting` props to the `Animated.View` tag. Add these and it works perfectly fine. Here's a working [Snack](https://snack.expo.dev/@kartikeyvaish/dialog-fadeinout) – Kartikey Jun 16 '22 at 08:43
  • @Kartikey, you are right. Adding those props fixes that snack, you can check it again. But for the life of me, in my app, which is just a slightly more complex version of the snack, the same code and code patterns result in the animations not working at all. I don't want to post some huge complex codebase. Where might I begin debugging this issue? – Seth Lutske Jun 16 '22 at 18:05

1 Answers1

5

So there is a clue to this in the expo docs on reanimated:

The new APIs in react-native-reanimated@2 use React Native APIs that are incompatible with Remote JS Debugging. Consequently, you can only debug apps using these APIs using Flipper, which is not yet available in the Expo managed workflow. You will be unable to use Remote JS Debugging if you use the new APIs from Reanimated 2. Remote JS Debugging will continue to work if you only use the APIs that were also available in Reanimated 1.

After doing some research, it seems that for a lot of people, using new APIs from react-native-reanimated@2 breaks their debugger. For me, its the other way around. I am using react-native-debugger. When I turn the debugger off, the animations work as expected. When I turn it back on, the animations simply dont work. (The exiting animation still seems not to work in certain cases).

Hopefully expo will work on this and improve the dev experience in the future. But at least its good to know this is only a development issue. Hopefully this answer helps someone else.

Seth Lutske
  • 9,154
  • 5
  • 29
  • 78