cheapsteak / react-transition-group-plus

A more full-featured transition group for React
Other
268 stars 20 forks source link

When set to "out-in", on "leave" the upcoming component appears before the leaving component #22

Open rossfishkind opened 7 years ago

rossfishkind commented 7 years ago

While transitioning routes, it seems that whenever I trigger my animation during componentWillLeave, the animation does not occur. While investigating this, it seems that the upcoming component is already in place of the component that is leaving.

As a side note, I have transitionMode set to out-in.

Here is what the routes looks like:

<TransitionSwitch location={location}>
  <AnimatedWrapper key={location.pathname}>
    {routes.map(({ path, component: Component, ...rest }) =>
      <TransitionRoute
        key={path}
        {...rest}
        path={`${match.url}/${path}`}
        render={props => <Component {...props} />}
      />,
    )}
  </AnimatedWrapper>
</TransitionSwitch>

I am utilizing the TransitionSwitch and TransitionRoute you posted a while back in conjunction with React Router v4.

This is what AnimatedWrapper looks like that wraps the routes:

import React from 'react';
import styled from 'styled-components';

export default class AnimatedWrapper extends React.Component {
  state = {
    duration: 400,
    status: null,
  };

  componentDidMount() {
    this.setState({
      status: 'mounted',
    });
  }

  componentWillAppear(cb) {
    this.setState({
      status: 'appear',
    });

    cb();
  }

  componentWillEnter(cb) {
    this.setState({
      status: 'enter',
    });

    setTimeout(() => {
      cb();
    }, this.state.duration);
  }

  componentWillLeave(cb) {
    this.setState({
      status: 'leave',
    });

    setTimeout(() => {
      cb();
    }, this.state.duration);
  }

  render() {
    const { children } = this.props;

    return (
      <Container status={this.state.status} duration={this.state.duration}>
        {children}
      </Container>
    );
  }
}

const Container = styled.div`
  height: 100%;

  .PageBody {
    opacity: 0.01;
    transform: translateY(16px);
    transition: opacity ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955),
      transform ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955);

    ${props => () => {
      if (props.status === 'enter' || props.status === 'appear') {
        return `
          opacity: 1;
          transform: translateY(0px);
        `;
      }
    }};
  }
`;

The enter transition works perfectly, but the leave transition does not. I even did a little test where I created a function called hide that did the same state change as componentWillLeave, and the animation was seamless. However, when componentWillLeave calls the same state change, it does nothing and the upcoming route comes into place instead. Any thoughts?

Thank you!

cheapsteak commented 7 years ago

Hi Ross

TransitionSwitch and TransitionRoute don't work yet right, we had to revert that :(

Do you still have the link to where I posted that? I need to update that

Sorry for the troubles

On Fri, Sep 8, 2017, 03:02 Ross Fishkind notifications@github.com wrote:

While transitioning routes, it seems that whenever I trigger my animation during componentWillLeave, the animation does not occur. While investigating this, it seems that the upcoming component is already in place of the component that is leaving.

As a side note, I have transitionMode set to out-in.

Here is what the routes looks like:

{routes.map(({ path, component: Component, ...rest }) => } />, )}

I am utilizing the TransitionSwitch and TransitionRoute you posted a while back in conjunction with React Router v4.

This is what AnimatedWrapper looks like that wraps the routes:

import React from 'react'; import styled from 'styled-components';

export default class AnimatedWrapper extends React.Component { state = { duration: 400, status: null, };

componentDidMount() { this.setState({ status: 'mounted', }); }

componentWillAppear(cb) { this.setState({ status: 'appear', });

cb();

}

componentWillEnter(cb) { this.setState({ status: 'enter', });

setTimeout(() => {
  cb();
}, this.state.duration);

}

componentWillLeave(cb) { this.setState({ status: 'leave', });

setTimeout(() => {
  cb();
}, this.state.duration);

}

render() { const { children } = this.props;

return (
  <Container status={this.state.status} duration={this.state.duration}>
    {children}
  </Container>
);

} }

const Container = styled.div` height: 100%;

.PageBody { opacity: 0.01; transform: translateY(16px); transition: opacity ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955), transform ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955);

${props => () => {
  if (props.status === 'enter' || props.status === 'appear') {
    return `
      opacity: 1;
      transform: translateY(0px);
    `;
  }
}};

} `;

The enter transition works perfectly, but the leave transition does not. I even did a little test where I created a function called hide that did the same state change as componentWillLeave, and the animation was seamless. However, when componentWillLeave calls the same state change, it does nothing and the upcoming route comes into place instead. Any thoughts?

Thank you!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/cheapsteak/react-transition-group-plus/issues/22, or mute the thread https://github.com/notifications/unsubscribe-auth/AAtaKPiaw9FMSYcQDX7-k7lzBRf8RHupks5sgOZ6gaJpZM4PQxhN .

rossfishkind commented 7 years ago

Ah, that makes sense. No worries!

Here is the CodeSandbox link where I found it: https://codesandbox.io/s/ KZp2AnrPG and here is the Github Issue that had the link: https://github.com/cheapsteak/react-transition-group-plus/issues/18

Will you be fixing it or removing the link for now? I know open-source maintenance can get a little time consuming, so totally cool if there are no plans at the moment. :)

Best, Ross

On Fri, Sep 8, 2017 at 6:02 AM, Chang Wang notifications@github.com wrote:

Hi Ross

TransitionSwitch and TransitionRoute don't work yet right, we had to revert that :(

Do you still have the link to where I posted that? I need to update that

Sorry for the troubles

On Fri, Sep 8, 2017, 03:02 Ross Fishkind notifications@github.com wrote:

While transitioning routes, it seems that whenever I trigger my animation during componentWillLeave, the animation does not occur. While investigating this, it seems that the upcoming component is already in place of the component that is leaving.

As a side note, I have transitionMode set to out-in.

Here is what the routes looks like:

{routes.map(({ path, component: Component, ...rest }) => } />, )}

I am utilizing the TransitionSwitch and TransitionRoute you posted a while back in conjunction with React Router v4.

This is what AnimatedWrapper looks like that wraps the routes:

import React from 'react'; import styled from 'styled-components';

export default class AnimatedWrapper extends React.Component { state = { duration: 400, status: null, };

componentDidMount() { this.setState({ status: 'mounted', }); }

componentWillAppear(cb) { this.setState({ status: 'appear', });

cb(); }

componentWillEnter(cb) { this.setState({ status: 'enter', });

setTimeout(() => { cb(); }, this.state.duration); }

componentWillLeave(cb) { this.setState({ status: 'leave', });

setTimeout(() => { cb(); }, this.state.duration); }

render() { const { children } = this.props;

return (

{children}

); } }

const Container = styled.div` height: 100%;

.PageBody { opacity: 0.01; transform: translateY(16px); transition: opacity ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955), transform ${props => props.duration}ms cubic-bezier(0.455, 0.030, 0.515, 0.955);

${props => () => { if (props.status === 'enter' || props.status === 'appear') { return opacity: 1; transform: translateY(0px); ; } }}; } `;

The enter transition works perfectly, but the leave transition does not. I even did a little test where I created a function called hide that did the same state change as componentWillLeave, and the animation was seamless. However, when componentWillLeave calls the same state change, it does nothing and the upcoming route comes into place instead. Any thoughts?

Thank you!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/cheapsteak/react-transition-group-plus/issues/22, or mute the thread https://github.com/notifications/unsubscribe-auth/AAtaKPiaw9FMSYcQDX7- k7lzBRf8RHupks5sgOZ6gaJpZM4PQxhN .

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/cheapsteak/react-transition-group-plus/issues/22#issuecomment-328097204, or mute the thread https://github.com/notifications/unsubscribe-auth/AAUNXQrILLq0c4lYgfpw5iIHSBuvHWBkks5sgTrogaJpZM4PQxhN .

cheapsteak commented 7 years ago

Thanks so much for the links!

It turned out to be a more difficult problem than we anticipated, we need to either trick RR4's Route component into still thinking it's matching even when it's in the componentWillLeave state, otherwise it'll immediately switch to the new component (so it's the same component animating "in" and "out") :(

The solution might not be as elegant as we'd hoped either, been procrastinating on getting it done in case a better solution sparks

rossfishkind commented 7 years ago

@cheapsteak gotcha, no problem!

For what it's worth, I followed this thread (https://github.com/ReactTraining/react-router/issues/4635#issuecomment-297828995) a bit and got the leave animation working. It's not perfect yet, I think I still need to modify some stuff, but this could be helpful in solving the issue.