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

[V3][iOS] Shared element transitions in nested stack stop working after navigation to parent stack,

Open CalypsoTechLTD opened this issue 1 year ago • 13 comments
trafficstars

Description

I'm using the latest expo router (v3.4.6) and have a expo router folder layout like follows:

(modals) (tabs)

Inside (tabs) there is a stack navigator with two screens where I have set up shared element transitions between the pages in the stack.

Everything works as expected until I navigate to a screen on the parent stacks (like a different tab or a screen in (modals)) at which point the shared element transitions stop working and goes back to the default animation without a shared element transition as can be seen from the examples below. (minimal reproducible demo linked).

The only workaround to this that I have found is resetting the animated component with a shared transition with a "key" prop every time the screen is focused, this makes the shared element work no matter where I navigate to, but obviously introduces flashing and unnecessary re-rendering. I've checked the same build on an android device but it works correctly.

This only happens AFTER the screen with the shared element transition has already been mounted once. If you navigate to a screen on those same parent stack navigators before navigating to where the shared element transitions are, it will still work, but only once.

Big thanks to the reanimated team for shared element transitions, they look and feel great apart from this issue. Perhaps it's an expo router thing.

https://github.com/software-mansion/react-native-reanimated/assets/149704513/8cb2671b-903e-4c8e-a9fa-41c283fea20a

https://github.com/software-mansion/react-native-reanimated/assets/149704513/719b44b8-499b-4cb0-8a44-51ede1c7ea32

Steps to reproduce

  1. Create a new expo project with create-expo-app
  2. Create a tab layout that has a nested stack navigator as one of it's screens.
  3. Create two pages in the stack navigator.
  4. Add shared element transitions between them.
  5. Navigate to stack with shared element transitions - works.
  6. Navigate to different tab in bottom tab navigator and navigate back to shared element stack - stops working.

Snack or a link to a repository

https://github.com/CalypsoTechLTD/shared-element-transition-issue

Reanimated version

3.6.2

React Native version

0.73.2

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo Dev Client

Architecture

Fabric (New Architecture)

Build type

Debug app & dev bundle

Device

Real device

Device model

iPhone 14 Pro (iOS 17.3)

Acknowledgements

Yes

CalypsoTechLTD avatar Feb 05 '24 17:02 CalypsoTechLTD

After some research, I believe this has to do with the fact that the unregisterTransition only gets called on component unmount, and in most navigators once the screens are mounted, they don't unmount. This behaviour stops and the SET starts working again, if you call

SharedTransition.prototype.registerTransition(viewTag, sharedElementTag)

manually on focus, and

SharedTransition.prototype.unregisterTransition(viewTag)

manually when the screen is not focused. This however makes the animation very jittery and I do not recommend. For anyone interested in a temporary hotfix, I suggest updating the key prop of the component to be animated whenever the screen the user is on, is not one of the shared element ones. In my application, it looks something like this:

  const pathname = usePathname();
  const shouldUpdate = !pathname.includes("events");
  const [key, setKey] = useState(0);

  useEffect(() => {
    if (shouldUpdate) {
      setKey((prev) => prev + 1);
    }
  }, [pathname]);

It would still be good to get some insight on this, we're happy to submit a PR if we get some more understanding on it.

CalypsoTechLTD avatar Feb 13 '24 10:02 CalypsoTechLTD

It would be great to get an answer on this, I am struggling with this also.

Poavei avatar Feb 13 '24 10:02 Poavei

any insights into this? @CalypsoTechLTD the key hotfix only works for me if I navigate between the screen with the animated component and a sibling screen twice in a row, which seems strange? then subsequent navigation works.

EDIT: ok, figured out my problem, even with the key prop hotfix, if I navigate to a screen that uses this library https://github.com/dohooo/react-native-reanimated-carousel it completely breaks shared element transitions once I go back.

alaughlin avatar Feb 16 '24 00:02 alaughlin

any solution now?

fukemy avatar Feb 16 '24 04:02 fukemy

any insights into this? @CalypsoTechLTD the key hotfix only works for me if I navigate between the screen with the animated component and a sibling screen twice in a row, which seems strange? then subsequent navigation works.

EDIT: ok, figured out my problem, even with the key prop hotfix, if I navigate to a screen that uses this library https://github.com/dohooo/react-native-reanimated-carousel it completely breaks shared element transitions once I go back.

@alaughlin I think I’m having this same issue with react-native-carousel, but to know for sure I need to remove it from my code, update key of elements and test going back without carousel. Will keep you posted. Basically for me after changing key and shareTransitionTag props I am experiencing the correct element animate back to original position but it gets frozen in that original position forevermore.

terence1990 avatar Feb 19 '24 02:02 terence1990

Any updates on this issue?

Hosam-hsm avatar Apr 01 '24 08:04 Hosam-hsm

Also hoping for updates here. Have tried implementing useIsFocused and modifying the key, also trying to force a re-render based on useIsFocused, no luck.

alexmgriffiths avatar Jul 17 '24 06:07 alexmgriffiths

+1

andyl-astardigital avatar Jul 17 '24 10:07 andyl-astardigital