0

This question is related to this post:

React Router v4 Match transitions using React Motion

...but I thought it deserved its own question.

I'm trying to figure out how to use the <MatchWithFade> example taken from here:

https://react-router.now.sh/animated-transitions

The problem I'm seeing is that if I have two tabs, and I want to fade between them, I'm only seeing the fade effect on one of the two tabs, and it depends on which <MatchWithFade> appears first in my code.

The relevant code is as follows:

const One = () => {
  return (
    <div style={{position:'absolute', top: 0, left: 0, width: 300, backgroundColor: 'orange'}}>
      One one one one one one one one one one
    </div>
  )
}

const Two = () => {
  return (
    <div style={{position:'absolute', top: 0, left: 0, width: 300, backgroundColor: 'yellow'}}>
      Two two two two two two two two two two
    </div>
  )
}

class AppBody extends Component {

  render () {

    return (
      <div style={{position: 'relative'}}>
        <MatchWithFade pattern='/one' component={One} />
        <MatchWithFade pattern='/two' component={Two} />
      </div>
    )
  }
}

In this example, navigating to /one, (using the React Router <Link> component) will cause the fade to happen, but if I navigate to /two, there is no fade. Then, if I list <MatchWithFade pattern='/two' ... /> first, then I see the fade transition to /two, but not /one.

Just using <Match> works fine, so I don't think it's a fundamental issue with how I have <BrowserRouter> configured.

I'm hoping that I'm just doing something silly, but for the life of me, I can't figure out what. Any guidance is appreciated.

UPDATE

I couldn't figure out how to made a jsbin using React Router (couldn't figure out how to reference the methods and objects on it, since I've only ever used RR via import statements). So here's the next best thing: this is a complete example that demonstrates this issue:

import React, { Component } from 'react';
import BrowserRouter from 'react-router/BrowserRouter'

import { TransitionMotion, spring } from 'react-motion'
import Match from 'react-router/Match'

import Link from 'react-router/Link';

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

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

const One = () => {
  return (
    <div style={{position:'absolute', top: 0, left: 0, width: 300, border: '1px solid black', backgroundColor: 'orange', minHeight: 200}}>
      One one one one one one one one one one<br />
      One one one one one one one one one one<br />
    </div>
  )
}

const Two = () => {
  return (
    <div style={{position:'absolute', top: 0, left: 0, width: 300, border: '1px solid black', backgroundColor: 'yellow', minHeight: 200}}>
      Two two two two two two two two two two<br />
      Two two two two two two two two two two<br />
    </div>
  )
}


class App extends Component {

  render () {
    return (
        <BrowserRouter>
          <div style={{padding: 12}}>
            <div style={{marginBottom: 12}}>
              <Link to='/one'>One</Link> || <Link to='/two'>Two</Link>
            </div>
            <div style={{position: 'relative'}}>
              <MatchWithFade pattern='/one' component={One} />
              <MatchWithFade pattern='/two' component={Two} />
            </div>
          </div>
        </BrowserRouter>
    )
  }
}

export default App;

There are only very minor differences between this MatchWithFade, and the one taken from the React Router docs. The biggest difference is that I pulled out the zIndex reference, but that did not affect the behavior.

If it's relevant, I started this project using create-react-app, and I'm using React Router version 4.0.0-alpha.6.

Community
  • 1
  • 1
hairbo
  • 3,113
  • 2
  • 27
  • 34
  • Nothing is standing out to me as wrong. Would you be able to put together a snippet, fiddle, jsbin, whatever you prefer with all of the code? (You'd probably have to switch to a hash router, but I don't think that that is the problem, so it should not matter) – Paul S Dec 22 '16 at 21:29
  • I can certainly try, yes. I'll do it today or tomorrow. – hairbo Dec 22 '16 at 21:30
  • i've added a complete example to the original post, above. I was able to reference React Router 4alpha6 from cdnjs, but I couldn't figure out how to reference the methods and objects on it, since I couldn't figure out the analogous call to `import BrowserRouter from 'react-router/BrowserRouter`. Anyway, I hope this is useful info. I'm still kind of assuming that I'm just doing something silly. Any guidance is helpful! – hairbo Dec 23 '16 at 20:15

1 Answers1

1

This is an issue with the style you're applying (or not) from the MatchWithFade example. Add zIndex: 1 back to your willLeave function, as this ensures the outgoing route is over top of the incoming in order to see the opacity fade.

Then add the absolute positioning back to the wrapper div you're applying the style to (styles.fill in the website example) so that they can overlap each other.

Here is a gist with your code fixed up.

jamesism
  • 206
  • 1
  • 3
  • 1
    Thanks for the reply, and sorry for the delayed response. I see what I did now, and I feel a bit foolish. `MatchWithFade` wraps the child component in its own `div`, and *that* is where the `position:absolute` is required. I was conflating that `div` with the root div of my `One` and `Two` components, so I put `position:absolute` in `One` and `Two`, but that's not the right place for it. Thanks again, and happy holidays! – hairbo Dec 26 '16 at 14:50