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

No back animations on iOS, instant transitions only

Open fahadfj opened this issue 2 years ago • 35 comments

Workaround found:

The problem was I was using use_frameworks! in my Podfile. The exact line I had was use_frameworks! :linkage => :static This was because the new react-native-firebase libraries (15.x.x) required this (all react-native-firebase > 14.x.x). For some reason this also made back animations stopped working.

I fixed this by downgrading react-native-firebase to 14.11.1 and removing use_frameworks! from my Podfile. Then I deleted the pods folder and reinstalled. Everything now works.

Description

UPDATE:

  • To fully replicate you must copy over the Podfile

UDPATE:

  • Appears to have something to do with using an Animated.View SplashScreen component, using a regular View doesn't interfere with the transitions

I updated to react native 0.69.1 and then I found that I no longer get back animations, the view in front disappears instantly.

  • I've tried using both useNavigation() and ({navigation}) in the screens arguments to trigger goBack(). There's still no transition animation either way
  • Swiping the page off works fine
  • If I enable headerShown: true then using the native back button on iOS plays the animations as normal
  • I've downgraded back to react native 0.68 and I've still go the same issue

It's the same issue as https://github.com/software-mansion/react-native-screens/issues/1356

Screenshots

https://user-images.githubusercontent.com/21344181/179496474-6fa6c511-49ea-443e-9be7-33a027597716.MP4

Steps To Reproduce

  1. Go back using goBack() (as opposed to a native back button).

Expected behavior

The transition should just play as normal

Actual behavior

There is no back animation when using goBack()

Reproduction

UPDATE: Reproduce this issue with the following code:

App.tsx

import * as React from 'react';
import {useEffect, useState} from 'react';
import {View, TouchableOpacity, Text} from 'react-native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {NavigationContainer} from '@react-navigation/native';
import Animated, {FadeOut} from 'react-native-reanimated';

const MainStack = createNativeStackNavigator();

function App() {
  const [userLoading, setUserLoading] = useState(true);

  useEffect(() => {
    setUserLoading(false);
  }, []);

  // Just show a splashscreen if either are loading
  if (userLoading) {
    return <SplashScreen />;
  }

  return (
    <NavigationContainer>
      <MainStack.Navigator>
        <MainStack.Screen name={'FirstScreen'} component={FirstScreen} />
        <MainStack.Screen name='SecondScreen' component={SecondScreen} />
      </MainStack.Navigator>
    </NavigationContainer>
  );
}

const FirstScreen = ({navigation}: any) => {
  return (
    <View style={{flex: 1, alignContent: 'center', justifyContent: 'center'}}>
      <TouchableOpacity
        style={{backgroundColor: 'cyan', padding: 20}}
        onPress={() => navigation.navigate('SecondScreen')}
      >
        <Text>Go forward</Text>
      </TouchableOpacity>
    </View>
  );
};

const SecondScreen = ({navigation}: any) => {
  return (
    <View style={{flex: 1, alignContent: 'center', justifyContent: 'center'}}>
      <TouchableOpacity
        style={{backgroundColor: 'magenta', padding: 20}}
        onPress={() => navigation.goBack()}
      >
        <Text>Go Back</Text>
      </TouchableOpacity>
    </View>
  );
};

const SplashScreen = () => {
  return (
    <Animated.View
      style={{
        backgroundColor: 'black',
        flex: 1,
      }}
      exiting={FadeOut}
    />
  );
};

export default App;

Podfile

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '13.0'
use_frameworks! :linkage => :static

target 'flashingscreens' do
  config = use_native_modules!

  # Flags change depending on the env values.
  flags = get_default_flags()

  use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => true,
    :fabric_enabled => flags[:fabric_enabled],
    # An absolute path to your application root.
    :app_path => "#{Pod::Config.instance.installation_root}/.."
  )

  target 'flashingscreensTests' do
    inherit! :complete
    # Pods for testing
  end

 post_install do |installer|

    # https://github.com/facebook/react-native/issues/32451
    installer.pods_project.targets.each do |target|
      if target.name == 'RCT-Folly'
        target.build_configurations.each do |config|
          config.build_settings['HEADER_SEARCH_PATHS'] = "$(inherited) ${PODS_ROOT}/fmt/include"
        end
      end
    end
    
end 
end

Platform

  • [x] iOS
  • [ ] Android
  • [ ] Web
  • [ ] Windows
  • [ ] tvOS

Architecture

  • [ ] Paper
  • [ ] Fabric

Workflow

  • [ ] Managed workflow
  • [x] Bare workflow

Package versions

"@react-navigation/native": "^6.0.11", "@react-navigation/native-stack": "^6.7.0",

package version
react-native 0.69.1
@react-navigation/native 6.0.11
@react-navigation/native-stack 6.7.0
react-native-screens 3.13.1
react-native-safe-area-context 4.3.1
react-native-gesture-handler 2.4.2
react-native-reanimated 2.9.1

I have tried earlier versions of react, react native, reanimated, native-stack

fahadfj avatar Jul 18 '22 10:07 fahadfj

Hey @fahadfj! Would you try using [email protected]? It is highly likely that this issue was already fixed, especially that [email protected] does not have support for [email protected].

Edit: also you should upgrade react-native-gesture-handler to 2.5.x as it is first version with official support to 0.69.x I believe

Let me know if bumping the version resolved the issues.

kkafar avatar Jul 18 '22 11:07 kkafar

Hey @kkafar ,

Thanks for taking this on, I've updated the libraries but sadly still the same issue (both screens and gesture handler).

fahadfj avatar Jul 18 '22 17:07 fahadfj

Ok, it gets interesting now ;D

The fact that intrigues me the most right now is that you restored your code to earlier version and the issue persisted. This points towards some cache problem. After restoring your project to previous version (the version that still worked correctly) you should try:

  1. Removing pods completely & reinstalling them: cd ios && rm -fr Pods build Podfile.lock && pod install && cd ... This step is important, because everytime you change minor version of react-native-screens most likely native code changes -> it is reasonable to reinstall the pods and build the native code from scratch.
  2. Reset your bundler cache: yarn start --reset-cache (or equivalent)
  3. Make sure, that package versions in your yarn.lock respond package versions from your package.json file.

Sadly, without reproduction I can't be of much more help for now.

kkafar avatar Jul 18 '22 17:07 kkafar

@kkafar I tried this but sadly it's the same issue.

If I can't create a minimal repro then what are my options? This is one of the most baffling bugs I've come across. I've been at it around 4 full days now

Also: While not minimal by any means I'd be willing to privately share the project (sans our private API keys).

fahadfj avatar Jul 18 '22 18:07 fahadfj

Can anyone advise how I could create a repro of this? We're a production app and falling behind atm, any advice/help would be appreciated

fahadfj avatar Jul 19 '22 12:07 fahadfj

Unfortunately I don't really know what might cause issues in your case as animations work properly on fresh applications & our example apps -> however it is possible, I doubt that this issue is caused only by react-native-screens.

I know it sounds ridiculous & naive, but these things sometimes work:

  1. Create new branch, git reset to last working version. Clear all cache you can think of (remove pods, node_modules) & re-install and try to run.
  2. Maybe try to clone fresh repo & run there?

Moreover, have you used Fabric with 0.69.1? If so, maybe you added (and did not remove) some Fabric specific configuration which causes this buggy behaviour?

kkafar avatar Jul 19 '22 13:07 kkafar

I tried this and it seems to be still there. What's the difference between navigation.goBack() and the native back button that appears in headerShown: true?

fahadfj avatar Jul 20 '22 19:07 fahadfj

I have found that if I use a regular stack navigator (not native), I get all the correct animations, BUT I cannot interact with the app anymore after I goBack(). If I use the react native inspector I cannot click anything either. What's going on here? Perhaps related https://github.com/software-mansion/react-native-screens/issues/21?

fahadfj avatar Jul 22 '22 16:07 fahadfj

@fahadfj I've tried reproduction you provided, but it works fine for me... :(

https://user-images.githubusercontent.com/50801299/180756554-9ae7637c-7e5e-4cfe-90ac-0b9b5a77032f.mov

kkafar avatar Jul 25 '22 10:07 kkafar

@kkafar I've tried again and I can reproduce it, have you used the same packages I'm using? AppDelegate.m

AppDelegate.m

#import "AppDelegate.h"

#import <AVFoundation/AVFoundation.h>  // import

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLinkingManager.h>


#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>


// LINKING
#import <React/RCTLinkingManager.h>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

#if RCT_DEV
#import <React/RCTDevLoadingView.h>
#endif

@implementation AppDelegate



- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil];  // allow
  
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                     moduleName:@"waProject"
                                              initialProperties:nil];

  rootView.backgroundColor = [UIColor colorWithRed: 0.15 green: 0.14 blue: 0.12 alpha: 1.00];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

// DEEP LINKING
- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

// UNIVERSAL LINKING
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
 return [RCTLinkingManager application:application
                  continueUserActivity:userActivity
                    restorationHandler:restorationHandler];
}

@end

https://user-images.githubusercontent.com/21344181/180776584-5d3df6ca-6807-4c19-8c4f-85ff5c93c396.mov

fahadfj avatar Jul 25 '22 12:07 fahadfj

@kkafar you must you use the Podfile provided in the original post, I have now replicated this in a fresh new react native project and I get the flashing

fahadfj avatar Jul 27 '22 16:07 fahadfj

@fahadfj Great to hear that you figured it out.

I've just looked at firebase website and found this paragraph (notice the blue note). I guess you have seen it already, but it nudges me towards opinion that this issue has broader scope than react-native-screens, however we will look into this.

kkafar avatar Jul 28 '22 09:07 kkafar

Hi, I used:

[ "expo-build-properties", { "ios": { "useFrameworks": "static" } } ], "@react-native-firebase/app",

for use firebase in development build, and also had problems with react-navigation animations. After deleting that - all done

fendermany avatar Sep 15 '22 10:09 fendermany

#https://github.com/react-navigation/react-navigation/issues/10843

fendermany avatar Oct 04 '22 08:10 fendermany

I am having the same issue.

I had to add use_frameworks because of the react-native firebase upgrade.

I am curious why use_frameworks is breaking the animations in react-native-screens.

punksta avatar Oct 28 '22 10:10 punksta

Why is this issue closed? Is the only solution to downgrade any packages that requires use-frameworks?

miladdev85 avatar Nov 03 '22 09:11 miladdev85

This issue is effectively blocking people who use react-native-firebase from upgrading to >= rnfb@15 and subsequently >= [email protected]. As the firebase-ios-sdk is not planning to remove use_frameworks, the only way forward for folks in this situation is to resolve why use_frameworks causes a break in animations. Can this be re-opened @kkafar?

austin43 avatar Nov 04 '22 19:11 austin43

Can we get a response from a maintainer here? Is there something else needed for us to re-open? Judging by the upvotes the previous comment got, my guess is this issue is pervasive in many dependent codebases.

The workaround posed here is not sufficient to support an upgrade path for react native apps relying on use_frameworks, which will be around for some time still.

Expo users are also now on a faster upgrade clock as SDK releases are happening every few months now, and thus deprecations happening quicker as well. If this is not resolved soon, many expo devs are going to be phased out of supported versions.

TLDR this is a serious issue that should be given at least a second look to determine if react-native-screens is the culprit, and if not, a path to which library is. Happy to help in any way I can. I believe the first step is re-opening the ticket.

austin43 avatar Dec 06 '22 07:12 austin43

I'll try to look into it

kkafar avatar Dec 06 '22 09:12 kkafar

Any news or progress regarding this?

miladdev85 avatar Dec 19 '22 18:12 miladdev85

Just to be clear - because of Firebase we need to add use_frameworks and this breaks the animation? I'm on React Native 0.69.3. Does this issue still exist on newer React Native versions?

miladdev85 avatar Jan 17 '23 10:01 miladdev85

Just to be clear - because of Firebase we need to add use_frameworks and this breaks the animation? I'm on React Native 0.69.3. Does this issue still exist on newer React Native versions?

Since my last test on expo sdk 47 (0.70.5), yes use_frameworks breaks the animation. As of firebase-ios-sdk 9 (rnfb 15), use_frameworks is required.

austin43 avatar Jan 17 '23 17:01 austin43

Just noticed something - don't know if this helps with anything but here goes: When having "Debug with Chrome" enabled, the back transition animations are working.

miladdev85 avatar Jan 20 '23 14:01 miladdev85

any luck?

mehthabux avatar Jan 31 '23 12:01 mehthabux

@miladdev85 I confirm I have the same issue. back animation works only when I enable debug mode. Sharing my package.json dependencies. "dependencies": { "@expo/vector-icons": "^13.0.0", "@invertase/react-native-apple-authentication": "^2.2.2", "@killerwink/lottie-react-native-color": "^1.0.2", "@react-native-firebase/app": "^16.6.0", "@react-native-firebase/auth": "^16.7.0", "@react-native-firebase/messaging": "^16.7.0", "@react-native-google-signin/google-signin": "^9.0.2", "@react-navigation/bottom-tabs": "^6.5.3", "@react-navigation/native": "^6.1.2", "@react-navigation/native-stack": "^6.9.8", "@reduxjs/toolkit": "^1.9.1", "@types/lodash": "^4.14.191", "axios": "^1.2.4", "expo": "~47.0.12", "expo-asset": "~8.7.0", "expo-build-properties": "~0.4.1", "expo-constants": "~14.0.2", "expo-dev-client": "~2.0.1", "expo-device": "~5.0.0", "expo-font": "~11.0.1", "expo-linking": "~3.3.0", "expo-splash-screen": "~0.17.5", "expo-status-bar": "~1.4.2", "expo-store-review": "~6.0.0", "expo-system-ui": "~2.0.1", "expo-updates": "~0.15.6", "expo-web-browser": "~12.0.0", "lodash": "^4.17.21", "lottie-react-native": "5.1.4", "react": "18.1.0", "react-devtools": "^4.27.1", "react-dom": "18.1.0", "react-native": "0.70.5", "react-native-gesture-handler": "~2.8.0", "react-native-purchases": "^5.8.0", "react-native-reanimated": "~2.12.0", "react-native-responsive-screen": "^1.4.2", "react-native-safe-area-context": "4.4.1", "react-native-screens": "~3.18.0", "react-native-ui-lib": "^6.28.3", "react-native-web": "~0.18.7", "react-query": "^3.39.2", "react-redux": "^8.0.5", "redux": "^4.2.0", "redux-persist": "^6.0.0", "redux-persist-expo-filesystem": "^2.0.0", "redux-thunk": "^2.4.2" }, "devDependencies": { "@babel/core": "^7.19.3", "@types/react": "~18.0.24", "@types/react-native": "~0.70.5", "jest": "^26.6.3", "jest-expo": "^47.0.0", "react-test-renderer": "18.1.0", "typescript": "^4.6.3" }

fa2id avatar Feb 11 '23 20:02 fa2id

A user on Reddit had issues with use_frameworks and solved it by using https://github.com/joncardasis/cocoapods-user-defined-build-types

This plugin allows for a Podfile to specify how each Pod (or multiple Pods) should be built (ex. as a dynamic framework).

And this is his Podfile which he helpfully posted on Reddit:

plugin 'cocoapods-user-defined-build-types'

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

platform :ios, '11.0'

$RNFirebaseAsStaticFramework = true

enable_user_defined_build_types!

target 'ProjectName' do
    config = use_native_modules!

    pod "Firebase", :build_type => :dynamic_framework
    pod "FirebaseCoreInternal", :build_type => :dynamic_framework 
    pod "FirebaseCore", :build_type => :dynamic_framework
    pod 'GoogleUtilities', :build_type => :dynamic_framework

    use_react_native!(
       :path => config[:reactNativePath\], 
       # to enable hermes on iOS, change `false` to `true` and then install pods
       :hermes_enabled => true
    )

    use_flipper!({ 'Flipper' => '0.171.0' })

    post_install do |installer|
        react_native_post_install(installer)

        # Disable arm64 builds for the simulator
        installer.pods_project.build_configurations.each do |config|
     config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
        end

        installer.pods_project.targets.each do |target|
          target.build_configurations.each do |config|
            config.build_settings['ENABLE_BITCODE'] = 'NO'
          end
        end
     end
end

I'm going to try this out today and hopefully this can be a workaround for this issue...

miladdev85 avatar Feb 16 '23 08:02 miladdev85

Thanks, @miladdev85 ! Please let us know how it goes.

fa2id avatar Feb 16 '23 08:02 fa2id

@fa2id I don't know what this exactly does or what the cons are, but animations are working now 🥳 @austin43 @mehthabux You guys might wanna give this a try also?

miladdev85 avatar Feb 16 '23 10:02 miladdev85

I'm not 100% sure what it does on the side of Firebase, but I managed to fix this issue by removing use_framework (like everyone else) and adding these two lines in my Podfile:

pod 'FirebaseCore', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true

RaphBlanchet avatar Feb 18 '23 17:02 RaphBlanchet

@RaphBlanchet RNFB maintainer recommends against this approach, as it could have undesired effects https://github.com/invertase/react-native-firebase/issues/6332#issuecomment-1287884131

austin43 avatar Feb 18 '23 18:02 austin43