Reputation: 43
I've been tearing my hair out all day trying to get this to work. What I'm noticing is that for whatever reason, the transition classes (classNames="fade") never get applied to the page elements. So when I navigate from one page to another, for a brief period (the timeout period) both of the page components will be displayed.
What I should have for 600ms...
<div class="RTG">
<div class="page fade-appear fade-enter fade-enter-active"> <!--
destination component HTML --></div>
<div class="page fade-exit fade-exit-active"> <!-- start component HTML --></div>
</div>
What I get is..
<div class="RTG">
<!-- "fade..." classes never applied to the child nodes" -->
<div class="page"> <!-- destination component HTML --></div>
<div class="page"> <!-- start component HTML --></div>
</div>
And then after the 600ms timeout, I'm left with...
<div class="RTG">
<div class="page"> <!-- destination component HTML --></div>
</div>
NOTE 1: I put the "RTG" className on the TransitionGroup component simply to verify that my "page" class components are actually direct descendants of the TransitionGroup component. Doesn't exist for any other reason.
NOTE 2: I'm using [email protected] because I have a compatibility issue with the latest version.
AppRouter.js
import PrivateRoute from './PrivateRoute';
import PublicRoute from './PublicRoute';
import { CSSTransition, TransitionGroup } from 'react-transition-group'
const AppRouter = () => (
<Router history={history}>
<Route render={({location}) => {
return (
<TransitionGroup className="RTG">
<CSSTransition
key={location.key}
timeout={600}
classNames="fade"
>
<Switch location={location}>
<PublicRoute path="/" component={LoginPage} exact={true} />
<PrivateRoute path="/dashboard" component={ExpenseDashboardPage} />
<PrivateRoute path="/create" component={AddExpensePage} />
<PrivateRoute path="/edit/:id" component={EditExpensePage} />
<Route component={NotFoundPage} />
</Switch>
</CSSTransition>
</TransitionGroup>
);
}} />
</Router>
);
export default AppRouter;
PrivateRoute.js
export const PrivateRoute = ({
isAuthenticated,
component: Component,
...rest
}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<div className="page">
<Header />
<Component {...props} />
</div>
) : (
<Redirect to="/" />
)
)} />
);
const mapStateToProps = (state) => ({
isAuthenticated: !!state.auth.uid
});
export default connect(mapStateToProps)(PrivateRoute);
PublicRoute.js
export const PublicRoute = ({
isAuthenticated,
component: Component,
...rest
}) => (
<Route {...rest} component={(props) => (
isAuthenticated ? (
<Redirect to="/dashboard" />
) : (
<div class="page">
<Component {...props} />
</div>
)
)} />
);
const mapStateToProps = (state) => ({
isAuthenticated: !!state.auth.uid
});
export default connect(mapStateToProps)(PublicRoute);
Applicable CSS Styles
.page {
position: absolute;
top: 0;
left: 0;
right: 0;
}
.fade-appear,
.fade-enter {
opacity: 0;
z-index: 1;
}
.fade-appear-active,
.fade-enter.fade-enter-active {
opacity: 1.0;
transition: opacity 300ms linear 150ms;
}
.fade-exit {
opacity: 1.0;
}
.fade-exit.fade-exit-active {
opacity: 0;
transition: opacity 150ms linear;
}
Upvotes: 1
Views: 3929
Reputation: 1274
Making fluid beautiful full page transitions can be tricky.
Most solutions implement it on the route
component.
Define the animations on a custom Link component. When user navigate, the next page will enter, and the current one will leave.
<Link
to="/some-path"
transition="glide-right"
/>
Of course, for that you must create your own link...
So you can use packages that does that, like react-tiger-transition.
(I'm the author)
Upvotes: 2
Reputation: 1293
Apparently you will need to wrap <Switch>
inside a parent component.
CSSTransition
works as it will try to inject classNames
to its children as props. Which means the child element will need to take these props and pass on as classNames
. Thus you will need to wrap <Switch>
into another component to make sure this mechanism works properly.
const AppRouter = () => (
<Router>
<Route
render={({ location }) => {
return (
<TransitionGroup className="RTG">
<CSSTransition key={location.key} timeout={600} classNames="fade">
<div>
<Switch location={location}>
<PublicRoute path="/" component={LoginPage} exact={true} />
<PrivateRoute
path="/dashboard"
component={ExpenseDashboardPage}
/>
<PrivateRoute path="/create" component={AddExpensePage} />
<PrivateRoute path="/edit/:id" component={EditExpensePage} />
<Route component={NotFoundPage} />
</Switch>
</div>
</CSSTransition>
</TransitionGroup>
);
}}
/>
</Router>
);
Upvotes: 5