react-navigation-shared-element icon indicating copy to clipboard operation
react-navigation-shared-element copied to clipboard

Shared element transition only works one time

Open TijsM opened this issue 4 years ago • 5 comments

bug

  • The shared element only works the first time after the app opens.
  • When going back from the detail screen, it's also not animated.

Expected behavior

The shared element transition works on all cards and when going back

Demo

https://user-images.githubusercontent.com/36442007/135582689-e0d557b5-f31f-4e88-884b-ce5d74958afa.mov

Code

app.tsx

const RootStack = createSharedElementStackNavigator()

return (
     <RootStack.Navigator
          initialRouteName="TabNav"
          screenOptions={{
            headerShown: false,
          }}
        >
          <RootStack.Screen name="TabNav" component={TabNav} />
          <RootStack.Screen
            name="ProductDetail"
            component={ProductDetail}
            sharedElements={route => {
              const { params } = route
              return ['headerImage' + params.id]
            }}
            options={{
              cardStyleInterpolator: ({ current: { progress } }) => {
                return { cardStyle: { opacity: progress } }
              },
            }}
          />
    </RootStack.Navigator>
)

Card.tsx

const ProductCard: FC<Props> = ({ product, style }) => {
  const navigation = useNavigation()

  const price = useLocalizePrice(priceDetails?.price, priceDetails.currency)

  return (
   <View
      testID={'product-card-' + name}
      style={style}
      onPress={() =>
        //@ts-ignore
        navigation.navigate('ProductDetail', {
          id: product.id,
        })
      }
    >
      <View>
        <SharedElement id={`headerImage${id}`}>
          <Image
            source={{
              uri: images.mainPicture,
            }}
            resizeMode="cover"
          />
        </SharedElement>
      </View>
    </View>
  )
}

Detail.tsx

export default function ProductDetail() {
  const { params } = useRoute<RouteProp<ParamList, 'productDetail'>>()
  const { id } = params

  const { bottom } = useSafeAreaInsets()
  const scrollY = useRef(new Animated.Value(0)).current


  const onScroll = Animated.event(
    [
      {
        nativeEvent: {
          contentOffset: {
            y: scrollY,
          },
        },
      },
    ],
    {
      useNativeDriver: true,
    }
  )

  return (
    <View bottom={bottom} testID="product-detail">
      <Animated.ScrollView
        showsVerticalScrollIndicator={false}
        onScroll={onScroll}
      >
        <SharedElement id={`headerImage${id}`} style={{ flex: 1 }}>
          <Image source={{ uri: images[0] }} />
        </SharedElement>
      </Animated.ScrollView>
    </View>
  )
}

TijsM avatar Oct 01 '21 07:10 TijsM

I got the exact same issue... here are my versions in case it helps:

"react-native-shared-element": "0.7.0",
"react-navigation-shared-element": "^3.1.3",
"@react-navigation/native": "~5.9.2",
"@react-navigation/stack": "^5.14.5",
"react-native-screens": "~3.4.0",

zhuangdaz avatar Oct 09 '21 03:10 zhuangdaz

Hi, this problem is not specific to the native extensions, but to react-navigation. Moving this to the react-navigation-shared-element repo

IjzerenHein avatar Oct 14 '21 07:10 IjzerenHein

I'm sorry this answer seems so late, but, only those who come later. I faced the same problem and the reason was I have two Stack in my app. One with react-navigation's createStackNavigator and the other with createSharedElementStackNavigator and the shared element transition only works the first time. After bringing both back to createSharedElementStackNavigator. Everything works fine. So try to check your project again

phuctranba avatar Dec 07 '21 08:12 phuctranba

hi @phuctranba

I'll definitely try this, I stopped using react-navigation-shared-element for this reason 😅

thanks!

TijsM avatar Dec 07 '21 08:12 TijsM

A late response from me as well but my issue was that I have my Stack navigator nested inside a Bottom tabs navigator which resulted in the sharedElements prop of the stack screen getting called with the current route only on the first navigation. Taking the screen out of the Bottom tabs worked but it might mess with your overall navigation architecture :(

chappie90 avatar Jul 24 '23 11:07 chappie90