'Animating route transitions with CSSTransitionGroup and React-Router v6
I'm starting to use React-Router v6, and running into issues animating route transitions.
Both the react-router docs and the react-transition-group docs specify ways that are not compatible with the new v6 api.
The primary reason seems to be the removal of the <Switch>
component.
In react-router@v5, this worked:
import { Router, Route, Switch, useLocation } from 'react-router@v5'
import { TransitionGroup, CSSTransition } from 'react-transition-group'
function App() {
const location = useLocation();
return (
<Router>
<TransitionGroup>
<CSSTransition key={location.key} classNames="fade" timeout={300}>
<Switch location={location}>
<Route path="/a" children={<A />} />
<Route path="/b" children={<B />} />
</Switch>
</CSSTransition>
</TransitionGroup>
</Router>
);
}
...However, in react-router@v6, this does not work:
function App() {
const location = useLocation();
return (
<Router>
<TransitionGroup>
<CSSTransition key={location.key} classNames="fade" timeout={300}>
<Routes location={location}>
<Route path="/a" element={<A />} />
<Route path="/b" element={<B />} />
</Routes>
</CSSTransition>
</TransitionGroup>
</Router>
);
}
It seems that the main difference is how <Switch>
accepted the Location
prop, and would keep both routes rendered long enough for the transtion to conclude.
Without that, it seems like route entrance animations are abrupt. Interesting, exit animations from nested routes appears to work correctly.
Any ideas how to get transition animations working with react-router v6?
Solution 1:[1]
It seems you want both respective components on screen at the same time; that is, the new component would be animating in while the old is animating out.
This was impossible before v6.0.0-beta.3.
But it is now possible (after v6.0.0-beta.3) thanks to the re-addition of the location
prop to the <Routes>
component. (release notes for v6.0.0-beta.3)
Your sample code only needs 2 modifications to work for [email protected], but needs the 3rd modification for the react-router@v6:
<Router>
should instead web compatible router, like<BrowserRouter>
.- The
useLocation()
hook must be used in the context of a router component. To fix that, you need a router wrapped in a parent component first, and then you're able to use the hook in any of router's child components. - Replace the
children
prop with theelement
prop, otherwise you'll get an error sayingall component children of <Routes> must either be a <Route> or <React.Fragment>.
Also – helpful to know for animated routes - "<TransitionGroup>
renders a <div>
by default" which can sometimes mess with animations. So it's helpful to pass component={null}
in props to stop it from doing that.
DEMO: All these changes are available here in this codesandbox:
Solution 2:[2]
There has been changes with react-router-v6. Read here and here
To get your animation working, replace Switch
with Routes
(no need to provide location). Provide element
prop to Route
. Also install history
library.
I have made a working demo using v6. Both entering and leaving animations are working. Compare the code with yours.
Solution 3:[3]
In the meantime, this issue was fixed. The issue was mentioned here here.
See a working code example here: here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Gelok |
Solution 2 | |
Solution 3 | mleister |