13

The animation transition example provided in the v4 docs seems a little convoluted to me, since it depicts fading the same component in and out and adjusting the background color.

I'm trying to apply this technique to a more real-world example of fading one component out and another in, however I can't get it to work properly (it only seems to fade the first one out, then the second one pops in, and this transition only works one way (back button results in no transition).

Here's my code, which uses a stripped down version of MatchWithFade from the example:

import React from 'react';
import { TransitionMotion, spring } from 'react-motion'
import { HashRouter, Match, Miss } from 'react-router';
import Home from './components/Home';
import Player from './components/Player';
import FormConfirmation from './components/FormConfirmation';

const App = () => (
  <HashRouter>
    <div className="App">
      <MatchWithFade exactly pattern="/" component={Home} />

      <MatchWithFade pattern="/player/:playerId" component={Player} />

      <MatchWithFade pattern="/entered" component={FormConfirmation} />

      <Miss render={(props) => (
        <Home players={Players} prizes={Prizes} {...props} />
      )} />
    </div>
  </HashRouter>
);

const MatchWithFade = ({ component:Component, ...rest }) => {
  const willLeave = () => ({ zIndex: 1, opacity: spring(0) })

  return (
    <Match {...rest} children={({ matched, ...props }) => (
      <TransitionMotion
        willLeave={willLeave}
        styles={matched ? [ {
          key: props.location.pathname,
          style: { opacity: spring(1) },
          data: props
        } ] : []}
      >
        {interpolatedStyles => (
          <div>
            {interpolatedStyles.map(config => (
              <div
                key={config.key}
                style={{...config.style}}
              >
                <Component {...config.data}/>
              </div>
            ))}
          </div>
        )}
      </TransitionMotion>
    )}/>
  )
}

export default App;

I realize that this question is nearly a duplicate of this one, however that one has an accepted answer that doesn't actually answer the question.

dougmacklin
  • 2,290
  • 9
  • 37
  • 66
  • I'm not particularly familiar with `react-motion`, but it looks like `` has a `willEnter` prop. Have you tried using that? – Paul S Dec 21 '16 at 05:20
  • Just a wild guess: Do you have fixed/absolute position set ? – ps-aux Nov 29 '17 at 14:39
  • I'm not too familiar with `react-motion` either, but looking at your code, I wonder if it has to do with the z-index you're trying to transition. Your default styles for the `TransitionMotion` component don't have a z-index, so this could be borking the transition. Try replacing that line with something like: `style: { zIndex: 2, opacity: spring(1) }` -- I don't know if the `spring` bit is necessary? But you may want to try wrapping your z-indexes with that as well. – Jonny Asmar Dec 23 '17 at 02:13
  • The first link is dead. Which demo are you referring to? – newguy Dec 26 '17 at 04:41
  • @newguy looks like the domain for their docs changed, I went ahead and updated the link so it should work now. I submitted this question over a year ago, however, so it's very likely that other things are also out of date as well. – dougmacklin Dec 26 '17 at 10:54

4 Answers4

1

react-motion is not good for large applications. Use react-transition-group instead.

Because react-motion use javascript to perform the transition. When making API call the transition will cross path(sync call in js) and make the transition laggy when route to new page. Where as react-transition-group use CSS to perform the transition.

Sreeram TP
  • 8,576
  • 5
  • 35
  • 77
Ibrahim
  • 186
  • 12
0

The v4 docs have moved to react-transition-group so you may consider to do the same.

With regards to "fading the same component in and out" it's not really the same instance of the Component. Two instances exist simultaneously and can provide the cross-fade. react-motion docs says "TransitionMotion has kept c around" and I imagine react-transition-group is the same.

Jayen
  • 4,499
  • 2
  • 34
  • 59
  • Thanks @Jayen, that makes sense. I submitted this question over a year ago, so it's more than likely very out of date. I personally am no longer looking for a solution to this problem, however I'm leaving it open as it still seems to receive a decent amount of traffic which leads me to believe that others are also looking for a better example than the docs provide. – dougmacklin Dec 26 '17 at 10:58
0

Here's an updated solution using react 16 and ReactCSSTransitionGroup from "react-addons-css-transition-group"

Edit zw0xv4vy3x

index.js

import React, { Component } from "react";
import ReactCSSTransitionGroup from "react-addons-css-transition-group";
import { render } from "react-dom";
import "./main.css";

function* continuosArrayIterator(arr) {
  let idx = 0;
  while (idx < arr.length) {
    let ret = arr[idx];
    idx++;
    if (idx === arr.length) {
      idx = 0;
    }
    yield ret;
  }
}

class App extends Component {
  constructor() {
    super();
    this.clickHandler = this.clickHandler.bind(this);
    this.items = [
      {
        id: 1,
        text: "item1",
        img: "https://mirrors.creativecommons.org/presskit/icons/cc.large.png"
      },
      {
        id: 2,
        text: "item2",
        img: "https://mirrors.creativecommons.org/presskit/icons/by.large.png"
      },
      {
        id: 3,
        text: "item3",
        img: "https://mirrors.creativecommons.org/presskit/icons/nc.large.png"
      },
      {
        id: 4,
        text: "item4",
        img:
          "https://mirrors.creativecommons.org/presskit/icons/nc-eu.large.png"
      }
    ];
    this.imageIterator = continuosArrayIterator(this.items);
    this.state = {
      image: this.imageIterator.next().value
    };
  }

  clickHandler(event) {
    return this.setState({
      image: this.imageIterator.next().value
    });
  }

  render() {
    return (
      <div>
        <button onClick={this.clickHandler}>Next Image</button>
        <ReactCSSTransitionGroup
          transitionAppear={true}
          transitionLeaveTimeout={500}
          transitionEnterTimeout={500}
          className="container"
          transitionName="example"
        >
          <div
            key={this.state.image.id}
            style={{
              position: "absolute",
              backgroundImage: `url(${this.state.image.img}`,
              backgroundSize: "auto 100px",
              height: "100px",
              width: "100px"
            }}
          />
        </ReactCSSTransitionGroup>
      </div>
    );
  }
}

render(<App />, document.getElementById("root"));

main.css

.container {
  position: absolute;
}

.example-enter {
  opacity: 0.01;
}

.example-enter.example-enter-active {
  opacity: 1;
  transition: opacity 500ms ease-in;
}

.example-leave {
  opacity: 1;
}

.example-leave.example-leave-active {
  opacity: 0.01;
  transition: opacity 500ms ease-in;
}

.example-appear {
  opacity: 0.01;
}

.example-appear.example-appear-active {
  opacity: 1;
  transition: opacity 0.5s ease-in;
}
Radu Luncasu
  • 757
  • 7
  • 16
  • Thank you for your submission, however I don't see how it relates to transition animations between routes with react-router. I submitted this question over a year ago, so it's more than likely very out of date. I personally am no longer looking for a solution to this problem, however I'm leaving it open as it still seems to receive a decent amount of traffic which leads me to believe that others are also looking for a better example than the docs provide. – dougmacklin Apr 13 '18 at 19:18
0

I didn't like the RRv4 example for animiations either. I ended up writing my own "AnimatedSwitch" for RRv4 Native.

I imagine it wouldn't take too much work to swap out the native animations for react-spring and be up and running.

https://javascriptrambling.blogspot.com/2020/07/react-router-native-animatedswitch.html

Kevin Williams
  • 194
  • 1
  • 5