IjzerenHein / react-navigation-shared-element

React Navigation bindings for react-native-shared-element 💫
https://github.com/IjzerenHein/react-native-shared-element
MIT License
1.27k stars 124 forks source link

Shared element transition only works one time #206

Open TijsM opened 2 years ago

TijsM commented 2 years ago

bug

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>
  )
}
zhuangdaz commented 2 years ago

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",
IjzerenHein commented 2 years ago

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

ghost commented 2 years ago

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

TijsM commented 2 years ago

hi @phuctranba

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

thanks!

chappie90 commented 1 year ago

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 :(