Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: swipe to go back does not work on Ionic React #20904

Closed
julien-terral opened this issue Mar 29, 2020 · 13 comments
Closed

bug: swipe to go back does not work on Ionic React #20904

julien-terral opened this issue Mar 29, 2020 · 13 comments
Labels
package: react @ionic/react package type: bug a confirmed bug report

Comments

@julien-terral
Copy link

julien-terral commented Mar 29, 2020

Bug Report

Ionic version : 5.0.1 (latest)
Variant used : React

Current behavior

On Ionic React, the transition of the swipe gesture to go back on the previous stacked screen is not working properly. When you route forward and then go back with the swipe gesture, I noticed that the swipe back gesture cause the animation to trigger twice.

The back button works fine, the issue is just regarding the swipe to go back gesture.

I've only been able to reproduce this on a physical iOS device (iPhone 11, iOS 13) because it seems working well via the iOS simulator.

Steps to reproduce

1. Open the app on your iOS device from http://beerodex-squid7331.firebaseapp.com
2. Click the "Goto page 2" button
3. Use the swipe back gesture to go back to the previous page

Video

This is a video of the occurrence :
https://streamable.com/32sm7

Related code

This is a link to my GitHub project :
https://github.com/Squid7331/react-ionic-swipegesture-issue

Other info

Same issue as this topic on Ionic Framework forum :
https://forum.ionicframework.com/t/swipe-back-gesture-on-ios-pwa-with-react-mixing-up/180024

Ionic info

Ionic:

Ionic CLI : 6.3.0
Ionic Framework : @ionic/react 5.0.7

Capacitor:

Capacitor CLI : 1.5.2
@capacitor/core : 1.5.2

Utility:

cordova-res : 0.11.0
native-run : 0.3.0

System:

NodeJS : v12.16.0
npm : 6.13.4

@ionitron-bot ionitron-bot bot added the triage label Mar 29, 2020
@lscardinali
Copy link

This happened to me too as i posted on the forum in December
https://forum.ionicframework.com/t/swipe-back-gesture-on-ios-pwa-with-react-mixing-up/180024/2
And got no answer.

I've tried to disable the swipe back gesture by adding to App.tsx
setupConfig({ swipeBackEnabled: false, });

And it does disable the Ionic's swipe back gesture, but the native one remains, which works, but when the swipe is completed and we're back on the first screen, the "pop" animation kicks in, resulting in a double animation again.
It can be seen here: https://streamable.com/ygjsy

This happens because apparently we cannot disable the Safari's default swipe back gesture.
While there's a history, the swipe back will work.

I'll be looking into how the Angular counterpart works, as it works as it should and apparently still uses the history

@liamdebeasi liamdebeasi added package: react @ionic/react package type: bug a confirmed bug report labels Mar 30, 2020
@liamdebeasi liamdebeasi changed the title bug: Swipe to go back gesture transition broken on iOS bug: swipe to go back does not work on Ionic React Mar 30, 2020
@liamdebeasi liamdebeasi added needs: investigation and removed type: bug a confirmed bug report labels Mar 30, 2020
@ccssmnn
Copy link

ccssmnn commented May 18, 2020

I guess the problem is that the first animation we see is the one provided by iOS Safari when using this gesture. You can test this on any site. After Safari successfully returns to the previous site (Safari animation finishes) the animation triggered by IonRouterOutlet starts. Thus we see the animation twice, since they are pretty similar.

The quick fix is to disable animations in IonRouterOutlet. Since this would remove the animation on all devices you can set that boolean dependent on the platform where your app is running with the isPlatform method from @ionic/react documented here.

@lucnat
Copy link

lucnat commented Jun 5, 2020

Any update on this? @ccssmnn with your solution you have no animations at all if you press the "go back" button..which is suboptimal.

@avilao
Copy link

avilao commented Jun 18, 2020

I also have the same issue. Any new solutions?

@uncvrd
Copy link

uncvrd commented Aug 2, 2020

Also confirming this issue on a PWA as well. I've disabled swipeBackEnabled for non capacitor devices in hopes this would prevent a duplicate animation with no luck unfortunately.

@lucnat
Copy link

lucnat commented Aug 29, 2020

As of now, disabling swipe back gesture as in https://ionicframework.com/docs/react/config works. Enabling it is still buggy, e.g. when used with a sidemenu. Also, it is not a smooth swipe back gesture, but snaps back once triggered.
Would love to see some improvements on that.

@Ripwords
Copy link

just like to update that this is still happening on vue pwa too

@MaxInMoon
Copy link

This is in my opinion a fundamental issue.

@Ripwords
Copy link

is this currently happening only on safari PWA or is it occurring in the native iOS app as well?

@apodogov
Copy link

Hello everyone.

I was playing first time with React and Ionic and came to this issue. Because it is "learning pet project", I had no time to investigate Ionic source, but I tried to do some workaround via available APIs.

It looks like I found a workaround (aka "ugly trick") for it and I'll describe it here, but I can't recommend to use it because:

  1. I agree with the message above that it is fundamental issue in framework, so it should be fixed on its level.
  2. It looks like my workaround is based on some another bug in framework, so maybe it won't work with newer versions.

Step 1

Of course, the first thing we need to do is

setupConfig({ swipeBackEnabled: false });

as described above because without this change behavior just can't be explained :)

But as a result, we have this problem:

And it does disable the Ionic's swipe back gesture, but the native one remains, which works, but when the swipe is completed and we're back on the first screen, the "pop" animation kicks in, resulting in a double animation again.

Step 2

I thought, can we disable only Ionic's "pop" animation?

And it is possible:

import { createAnimation, iosTransitionAnimation, setupConfig } from '@ionic/core';

const animationBuilder = (baseEl, opts) => {
  if (opts.direction === "back") {
    return createAnimation(); // TODO: not sure if it is correct way to create empty animation
  }

  return iosTransitionAnimation(baseEl, opts);
};

setupConfig({
  swipeBackEnabled: false,
  navAnimation: animationBuilder
});

As a result, when user selects list item on my first page, Ionic's "push" animation works and when user swipes back, only native iOS animation works.

But of course, animation disappeared from click on "Back" button.

Step 3

Can we override global animation builder only for "Back" button?

Yes:

<IonBackButton routerAnimation={iosTransitionAnimation} />

As a result:

  1. Go to second page and swipe back - works.
  2. Go to second page and tap "Back" - works.
  3. Yay!
  4. Double check: Go to second page and swipe back - second animation appears again :(

Step 4

So, swipe back (analog of browser's "Back" button) and Ionic's back button work differently.

After second animation appears, it won't disappear after further "Back" buttons or swipes back. But I also noticed interesting fact that if user goes to second page via swiping right (analog of browser's "Forward" button) and swipes back again, then second animation disappears again.

I tried to find what was the difference in two navigations back and found that when browser's "Back" button (or swipe back) was used, the method componentWillUnmount was not called for the second component.

As a result, the following "trick" came to my mind. Ugly, but it is lesser from evils.

<IonBackButton routerAnimation={this.animationBuilder} />
  constructor(props) {
    super(props);

    this.animationBuilder = this.animationBuilder.bind(this);
    this.willUnmount = false;
  }
  
  componentWillUnmount() {
    this.willUnmount = true;
  }

  animationBuilder(baseEl, opts) {
    if (this.willUnmount) {
      return createAnimation(); // TODO: not sure if it is correct way to create empty animation
    }

    return iosTransitionAnimation(baseEl, opts);
  }

It works well for my app, but I expect that it is not universal approach. And again, it looks like it is based on a bug, so think twice before applying it :)

@BerkeAras
Copy link

Hello everyone.

I was playing first time with React and Ionic and came to this issue. Because it is "learning pet project", I had no time to investigate Ionic source, but I tried to do some workaround via available APIs.

It looks like I found a workaround (aka "ugly trick") for it and I'll describe it here, but I can't recommend to use it because:

  1. I agree with the message above that it is fundamental issue in framework, so it should be fixed on its level.

  2. It looks like my workaround is based on some another bug in framework, so maybe it won't work with newer versions.

Step 1

Of course, the first thing we need to do is


setupConfig({ swipeBackEnabled: false });

as described above because without this change behavior just can't be explained :)

But as a result, we have this problem:

And it does disable the Ionic's swipe back gesture, but the native one remains, which works, but when the swipe is completed and we're back on the first screen, the "pop" animation kicks in, resulting in a double animation again.

Step 2

I thought, can we disable only Ionic's "pop" animation?

And it is possible:


import { createAnimation, iosTransitionAnimation, setupConfig } from '@ionic/core';



const animationBuilder = (baseEl, opts) => {

  if (opts.direction === "back") {

    return createAnimation(); // TODO: not sure if it is correct way to create empty animation

  }



  return iosTransitionAnimation(baseEl, opts);

};



setupConfig({

  swipeBackEnabled: false,

  navAnimation: animationBuilder

});

As a result, when user selects list item on my first page, Ionic's "push" animation works and when user swipes back, only native iOS animation works.

But of course, animation disappeared from click on "Back" button.

Step 3

Can we override global animation builder only for "Back" button?

Yes:


<IonBackButton routerAnimation={iosTransitionAnimation} />

As a result:

  1. Go to second page and swipe back - works.

  2. Go to second page and tap "Back" - works.

  3. Yay!

  4. Double check: Go to second page and swipe back - second animation appears again :(

Step 4

So, swipe back (analog of browser's "Back" button) and Ionic's back button work differently.

After second animation appears, it won't disappear after further "Back" buttons or swipes back. But I also noticed interesting fact that if user goes to second page via swiping right (analog of browser's "Forward" button) and swipes back again, then second animation disappears again.

I tried to find what was the difference in two navigations back and found that when browser's "Back" button (or swipe back) was used, the method componentWillUnmount was not called for the second component.

As a result, the following "trick" came to my mind. Ugly, but it is lesser from evils.


<IonBackButton routerAnimation={this.animationBuilder} />


  constructor(props) {

    super(props);



    this.animationBuilder = this.animationBuilder.bind(this);

    this.willUnmount = false;

  }

  

  componentWillUnmount() {

    this.willUnmount = true;

  }



  animationBuilder(baseEl, opts) {

    if (this.willUnmount) {

      return createAnimation(); // TODO: not sure if it is correct way to create empty animation

    }



    return iosTransitionAnimation(baseEl, opts);

  }

It works well for my app, but I expect that it is not universal approach. And again, it looks like it is based on a bug, so think twice before applying it :)

Thanks for that great workaround!!!
I will directly start trying to find a solution (maybe based on the workaround?).

@liamdebeasi
Copy link
Contributor

liamdebeasi commented Apr 29, 2022

Thanks for the issue. There are a couple issues here:

  1. Ionic React does not implement the swipe to go back gesture correctly. When you begin to swipe, the page transition kicks in and completes. It does not allow for a smooth swipe back experience. This issue is being tracked in bug: react swipe to go back does not implement gesture properly #22342.
  2. When running an Ionic app in a mobile browser or as a PWA on iOS, users have to deal with both Ionic's swipe back gesture as well as iOS's built in swipe back gesture. This is being tracked in bug: ios, cannot disable Safari swipe to go back when running as PWA #22299.

To explain issue 2 a bit more:

When you set swipeGesture={false} on IonRouterOutlet, this only disables Ionic's swipe gesture. It does not disable the browser's swipe gesture. Additionally, when you route forward/back, Ionic runs a page transition.

So what is happening is when you swipe back, you first get the swipe back gesture from iOS. When the transition completes, Ionic runs its own page transition. Visually it appears as though there are duplicate transitions happening.


Given that these issues have different requirements for resolving them, I am going to close this thread in favor of the two issues I linked to above. Please follow those threads for updates on these issues.

Thank you!

@ionitron-bot
Copy link

ionitron-bot bot commented May 29, 2022

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators May 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
package: react @ionic/react package type: bug a confirmed bug report
Projects
None yet
Development

No branches or pull requests