react-swipeable-views icon indicating copy to clipboard operation
react-swipeable-views copied to clipboard

First index change is broken

Open nikandlv opened this issue 4 years ago • 19 comments

The first time you change the index it won't animate. Here's a demo https://material-ui.com/components/tabs/#full-width

nikandlv avatar Jun 09 '20 13:06 nikandlv

Bug present in Chrome but not FireFox

eprice122 avatar Jun 13 '20 16:06 eprice122

The bug is present on: Chrome v83 Firefox v77 Safari v12

Any idea where in the codebase to start looking at fixing this? I would like to take a look. @oliviertassinari

peitalin avatar Jun 23 '20 04:06 peitalin

Did some digging,

When the component first mounts, displaySameSlide is initially true, causing transition = “all 0s ease 0s” when then component first mounts. So the 1st index change does not animate.

image

Then after the 1st transition, the computed displaySameSlide then becomes false (calculated in componentsWillReceiveProps), after which the calculated transition = “transform 0.35s cubic-bezier(0.15, 0.3, 0.25, 1) 0s”, which enables the transition animation thereafter.

image

peitalin avatar Jun 23 '20 11:06 peitalin

Hi! Is there any word on this? It's quite annoying! Thanks for the library either way, it's great!

lord0gnome avatar Jul 12 '20 16:07 lord0gnome

This is not a perfect solution, but if you take advantage of the containerStyle property you can get the initial slide to transition correctly...

<SwipeableViews
    containerStyle={{
        transition: 'transform 0.35s cubic-bezier(0.15, 0.3, 0.25, 1) 0s'
    }}
    ...

I3rendan avatar Jul 13 '20 14:07 I3rendan

Ah, Thank you very much!!! Works like a charm, true that it is imperfect but so is my application so I can't judge it. XD Also worth noting for some reason I don't have this issue when I use my webapp in a ios safari browser(I read above it's mostly a chrome bug, could be why)

lord0gnome avatar Jul 13 '20 15:07 lord0gnome

@I3rendan its a good workaround until the pull request is merged

nikandlv avatar Jul 15 '20 08:07 nikandlv

the bug is still existing on Chrome 85.0

sdutwsl avatar Sep 27 '20 08:09 sdutwsl

the bug is still existing on Chrome 86

kahirokunn avatar Oct 29 '20 01:10 kahirokunn

issue still not resolved with chrome. please fix it.

Meet008 avatar Jan 27 '21 12:01 Meet008

I did some digging in https://github.com/mui-org/material-ui/issues/22351#issuecomment-778660214, this seems to fix the issue:

diff --git a/packages/react-swipeable-views/src/SwipeableViews.js b/packages/react-swipeable-views/src/SwipeableViews.js
index b25b743..4e8ea1e 100644
--- a/packages/react-swipeable-views/src/SwipeableViews.js
+++ b/packages/react-swipeable-views/src/SwipeableViews.js
@@ -763,6 +763,11 @@ So animateHeight is most likely having no effect at all.`,
       }
     }

+    // Workaround bug https://github.com/oliviertassinari/react-swipeable-views/issues/599.
+    if (this.containerNode) {
+      this.containerNode.style.WebkitTransition = WebkitTransition;
+      this.containerNode.style.transition = transition;
+    }
+
     const containerStyle = {
       height: null,
       WebkitFlexDirection: axisProperties.flexDirection[axis],

oliviertassinari avatar Feb 13 '21 18:02 oliviertassinari

I have the exact problem as well. The initial element has this style applied to it :

element.style {
    flex-direction: row;
    transition: all 0s ease 0s;
    direction: ltr;
    display: flex;
    will-change: transform;
    transform: translate(-100%, 0px);
}

After the first transition, the transition is set correctly

element.style {
    flex-direction: row;
    transition: transform 0.35s cubic-bezier(0.15, 0.3, 0.25, 1) 0s;
    direction: ltr;
    display: flex;
    will-change: transform;
    transform: translate(0%, 0px);
}

yanickrochon avatar Feb 25 '21 20:02 yanickrochon

@oliviertassinari Do you think there's any issue with setting displaySameSlide: false as the default? When I change it this issue goes away altogether.

Diff:

diff --git a/packages/react-swipeable-views/src/SwipeableViews.js b/packages/react-swipeable-views/src/SwipeableViews.js
index 0647853..9ff5193 100644
--- a/packages/react-swipeable-views/src/SwipeableViews.js
+++ b/packages/react-swipeable-views/src/SwipeableViews.js
@@ -246,7 +246,7 @@ class SwipeableViews extends React.Component {
       renderOnlyActive: !props.disableLazyLoading,
       heightLatest: 0,
       // Let the render method that we are going to display the same slide than previously.
-      displaySameSlide: true,
+      displaySameSlide: false,
     };
     this.setIndexCurrent(props.index);
   }

PR: #639

leontastic avatar Feb 28 '21 01:02 leontastic

Bug is still here..

gaojude avatar Dec 14 '21 22:12 gaojude

Still actual

mrgazanfarli avatar Feb 13 '22 20:02 mrgazanfarli

AFAIK the latest version of react-swipeable-views that doesn't have problems with animation on first transition and can start with index != 0 is 0.12.10. In order to install it with new React version you have to use --force flag. You'll also get warnings in the console when using it. Since it's four years old you will get 5 vulnerabilities (4 low, 1 high) in your code.

kubagp1 avatar Feb 16 '22 20:02 kubagp1

I'm still running into this error, and by default this shouldn't be happening, so the bug still needs to be fixed...

roninMo avatar Apr 25 '22 19:04 roninMo

The same here. Is anybody taking a look at this bug?

The workaround provided by @I3rendan is good for the most of cases, however there is a scenario where this causes strange behavior: If you want to initially start showing the second view (or any view except the first one), you will see an undesired initial animation after the component is rendered for the first time.

davloperez avatar May 03 '22 17:05 davloperez

This is kind of a hack but you can use something like this:

function useDelayedIsMounted(timeout = 0) {
  const [isMounted, setIsMounted] = useState(false);

  useEffect(() => {
    setTimeout(() => {
      setIsMounted(true);
    }, timeout);
  }, []);

  return isMounted;
}

...

const isMounted = useDelayedIsMounted(10);

...

containerStyle={
  isMounted
    ? {
      transition: 'transform 0.35s cubic-bezier(0.15, 0.3, 0.25, 1) 0s',
    } : {}
 }

tldr: wait a couple ms after mounting to apply the CSS that fixes this bug.

shawngustaw avatar Sep 20 '23 19:09 shawngustaw