reactjsreact-nativereact-navigation-v5shared-element-transition

React Navigation Shared Element 5 Nested Navigators


I'm running into a little issue with react-navigation-shared-element 5, so I made a very basic app to show an example. Basically I have a tab navigator nested in a stack navigator and when navigating to the tab navigator I'd like for a shared element transition. This is what I have so far. The transition was working when I had both MainScreen and OtherScreen in the Stack Navigator, but when I moved OtherScreen to the tab navigator it stopped.

import {NavigationContainer} from '@react-navigation/native';
import MainScreen from './src/MainScreen';
import OtherScreen from './src/OtherScreen';
import OtherScreenSecond from './src/OtherScreenSecond';
import {createSharedElementStackNavigator} from 'react-navigation-shared-element';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

const Stack = createSharedElementStackNavigator();
const Tab = createBottomTabNavigator();

const TabStuff = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen name="OtherScreen" component={OtherScreen} />
      <Tab.Screen name="OtherScreenSecond" component={OtherScreenSecond} />
    </Tab.Navigator>
  );
};

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator mode="modal" headerMode="none">
        <Stack.Screen name="MainScreen" component={MainScreen} />
        <Stack.Screen name="Tabs" component={TabStuff} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;
import {View, Text, StyleSheet, TouchableOpacity} from 'react-native';
import {SharedElement} from 'react-navigation-shared-element';

const MainScreen = (props) => {
  return (
    <View style={{...styles.container}}>
      <SharedElement id="test">
        <View
          style={{
            width: 100,
            height: 100,
            justifyContent: 'center',
            alignItems: 'center',
            borderRadius: 50,
            backgroundColor: 'orange',
            marginBottom: 50,
          }}></View>
      </SharedElement>
      <TouchableOpacity onPress={() => props.navigation.navigate('Tabs')}>
        <Text>Next</Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'red',
  },
});

export default MainScreen;
import {View, Text, StyleSheet, TouchableOpacity} from 'react-native';
import {SharedElement} from 'react-navigation-shared-element';

const OtherScreen = (props) => {
  return (
    <View style={{...styles.container}}>
      <SharedElement id="test">
        <View
          style={{
            width: 150,
            height: 150,
            justifyContent: 'center',
            alignItems: 'center',
            borderRadius: 75,
            backgroundColor: 'blue',
            marginBottom: 50,
          }}></View>
      </SharedElement>
      <TouchableOpacity onPress={() => props.navigation.pop()}>
        <Text>Back</Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'yellow',
  },
});

OtherScreen.sharedElements = (route, otherRoute, showing) => {
  return ['test'];
};

export default OtherScreen;

Any pointers would be greatly appreciated, thanks!


Solution

  • You have to add sharedElementsConfig to Stack. Screen specifying the id of the shared element to work while navigating back

    Change code to:

    const App = () => {
      return (
        <NavigationContainer>
          <Stack.Navigator mode="modal" headerMode="none">
            <Stack.Screen 
              name="MainScreen" 
              sharedElementsConfig={(props) => [
                {
                  id: 'test', animation: 'fade' 
                }
              ]} 
              component={MainScreen} />
            <Stack.Screen name="Tabs" component={TabStuff} />
          </Stack.Navigator>
        </NavigationContainer>
      );
    };