D.jennis
D.jennis

Reputation: 199

How to make page slide(change) with react-router

I'v tried to use react-router and ReactTransitionGroup to make an navigation effect(page slide whereas route changes).

However, it's error-prone and ugly.(made much logic to define which direction to slide to and remove/add classes to make transition work).

I doubt is there any nice plugin to use.

Here's piece of my code, which inspired by Hardware-Accelerated Page Transitions for Mobile Web Apps / PhoneGap Apps.

const keyHistory = [];

let dir = 0;

const PageMixin = {
    componentWillAppear(cb) {
        keyHistory.push(this.props.location.key);

        let $el = $(ReactDom.findDOMNode(this));

        $el.addClass(pageStyles.right);

        $el.one('transitionend', () => {
            $el.removeClass(`${pageStyles.right} ${pageStyles.active}`);
            cb();
        });

        requestAnimationFrame(() => {
            $el.addClass(`${pageStyles.active} ${pageStyles.center}`);
        });
    },

    componentWillEnter(cb) {
        let key = this.props.location.key,
            len = keyHistory.length; 
        if (key === keyHistory[len - 2]) {
            keyHistory.pop();
            dir = -1;
        } else {
            keyHistory.push(key);
            dir = 1;
        }

        const fromDir = dir === -1 ? pageStyles.left : pageStyles.right;

        let $el = $(ReactDom.findDOMNode(this));

        $el.addClass(fromDir);

        requestAnimationFrame(() => {
            $el.removeClass(fromDir).addClass(`${pageStyles.active} ${pageStyles.center}`);
        });

        $el.one('transitionend', () => {
            $el.removeClass(`${fromDir} ${pageStyles.active}`);
            cb();
        });


    },

    componentWillLeave(cb) {

        const toDir = dir === -1 ? pageStyles.right : pageStyles.left;

        let $el = $(ReactDom.findDOMNode(this));

        requestAnimationFrame(() => {
            $el.removeClass(pageStyles.center).addClass(`${pageStyles.active} ${toDir}`);
        });

        $el.one('transitionend', () => {
            $el.removeClass(pageStyles.active);
            cb();
        });
    }
};

Upvotes: 6

Views: 8583

Answers (3)

Matan Bobi
Matan Bobi

Reputation: 2813

Coming in abit late but, without any other packages, There's a nice example in the examples of react-router right Here

Using ReactCSSTransitionGroup would look like this:

<ReactCSSTransitionGroup
     component="div"
     transitionName={ location.action !== 'POP' ? 'slide': 'slide-back' }
     transitionEnterTimeout={1000}
     transitionLeaveTimeout={1000}>
      {React.cloneElement(children, { key: location.pathname })}
</ReactCSSTransitionGroup>

for the slide you can use the method shown in Sliding React Components:

.slide-enter {
  transform: translate(100%);
}
.slide-enter.slide-enter-active {
  transform: translate(0%);
  transition: transform 1000ms ease-in-out;
}
.slide-leave {
  transform: translate(0%);
}
.slide-leave.slide-leave-active {
  transform: translate(-100%);
  transition: transform 1000ms ease-in-out;
}

.slide-back-enter{
  transform: translate(-100%);
}

.slide-back-enter.bg-back-enter-active {
  transform: translate(0%);
  transition: transform 1000ms ease-in-out;
}
.slide-back-leave {
  transform: translate(0%);
}
.slide-back-leave.bg-back-leave-active {
  transform: translate(0%);
  transition: transform 1000ms ease-in-out;
}

Upvotes: 2

Olivier Tassinari
Olivier Tassinari

Reputation: 8681

You could be interested having a look at https://github.com/doctolib/react-router-transitions. This plugin handles the logic part of the transition.

You would still have to handle the actual transition on your side. E.g. by using ReactTransitionGroup.

Upvotes: 2

Jackie Huang
Jackie Huang

Reputation: 145

You can try this

https://github.com/oliviertassinari/react-swipeable-views

Partial code from github

  <SwipeableViews>
    <div>
      slide 1
    </div>
    <div>
      slide 2
    </div>
    <div>
      slide 3
    </div>
  </SwipeableViews>

Upvotes: 2

Related Questions