react-transition-group
react-transition-group copied to clipboard
Cannot get CSSTransition and Route to work
Hi I am hoping for a bit of help here if possible. I cannot get transition group to work. The routing works fine but there are no transitions and the console.log("FIRED") isn't outputted either. I believe the Switch component isn't supported here and that maybe what is causing the problem? However I cannot find the right documentation to tell me what to change it to. Here is a simple example where specific components fade in and out at the same time when a link is clicked. I also get an error in strict mode in the console which I'll post at the bottom. Can anyone help me please?
import * as React from 'react'
import {
HashRouter as Router,
Link,
Switch,
Route,
Redirect,
useParams,
useLocation
} from "react-router-dom";
import {TransitionGroup, CSSTransition} from "react-transition-group";
const TransGroup = () =>{
const location = useLocation();
return(
<>
<div className={"w-full h-full"}>
<Router>
<div className={"fill w-full"}>
<ul className={"nav overflow-hidden mb-8 flex "}>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/"}>Red</Link></li>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/purple"}>Purple</Link></li>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/blue"}>Blue</Link></li>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/yellow"}>Yellow</Link></li>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/pink"}>Pink</Link></li>
<li><Link className={"bg-white p-8 m-8 text-black inline-block"} to={"/aqua"}>Aqua</Link></li>
</ul>
</div>
</Router>
<div className={"fill content w-full h-full"}>
<Route render={({location}) =>(
<TransitionGroup>
<CSSTransition
timeout={5000}
onEnter={() => {
console.log('FIRED!');
}}
classNames={{
appear: 'my-node-appear',
appearActive: 'my-node-active-appear',
appearDone: 'my-node-done-appear',
enter: 'my-node-enter',
enterActive: 'my-node-active-enter',
enterDone: 'my-node-done-enter',
exit: 'my-node-exit',
exitActive: 'my-node-active-exit',
exitDone: 'my-node-done-exit',
}}
key={location.key}
>
<Switch>
<Route exact path={"/"}>
<div className={"bg-red-500 text-white w-full h-16"}>
RED
</div>
</Route>
<Route path={"/purple"}>
<div className={"bg-lcnuk-other text-white w-full h-16"}>
PURPLE
</div>
</Route>
<Route path={"/blue"}>
<div className={"bg-blue-500 text-white w-full h-16"}>
BLUE
</div>
</Route>
<Route path={"/yellow"}>
<div className={"bg-lcnuk-other text-white w-full h-16"}>
YELLOW
</div>
</Route>
<Route path={"/pink"}>
<div className={"bg-white text-black w-full h-16"}>
PINK
</div>
</Route>
<Route path={"/aqua"}>
<div className={"bg-black text-white w-full h-16"}>
AQUA
</div>
</Route>
<Route path={'*'}>
<div>Not Found</div>
</Route>
</Switch>
</CSSTransition>
</TransitionGroup>
)} />
</div>
</div>
</>
)
}
export default TransGroup
**I'm a bit stuck as React is something I'm new to and looking at other examples I cannot see how they relate to my project as they look so different. Here is the error in console:
Warning: Legacy context API has been detected within a strict-mode tree.
The old API will be supported in all 16.x releases, but applications using it should migrate to the new version.
Please update the following components: Transition, TransitionGroup
Learn more about this warning here: https://reactjs.org/link/legacy-context TransitionGroup@http://localhost:3000/static/js/vendors~main.chunk.js:328926:30 Route@http://localhost:3000/static/js/vendors~main.chunk.js:324374:29 div div TransGroup@http://localhost:3000/static/js/main.chunk.js:1450:88 Router@http://localhost:3000/static/js/vendors~main.chunk.js:324005:30 HashRouter@http://localhost:3000/static/js/vendors~main.chunk.js:323573:35 index.js:1**
Anyone know where I'm going wrong please?
@cannon303 Here's a codesandbox example that should be helpful!
- https://codesandbox.io/s/react-transition-routes-with-noderef-k9q47?file=/src/App.tsx
Essentially, each Route
needs it's own CSSTransition
, and each CSSTransition
needs a nodeRef
for the individual route.
////// CONTENT TRANSITION ROUTER
const PageContent = withRouter(({ location }) => {
let routeRefs: any[] = [];
const isMatch = useCallback(
(path: string): boolean => {
return location.pathname === path ?? false;
},
[location]
);
return (
<>
{appRoutes.map(({ path, Component }, index) => {
routeRefs[index] = React.useRef(null);
return (
<Route key={index} exact path={path}>
{() => {
// Route callback ensures the transitions are loaded correctly
return (
<CSSTransition
nodeRef={routeRefs[index]}
in={isMatch(path)}
timeout={300}
classNames="fade"
unmountOnExit
appear
>
<div ref={routeRefs[index]} className="fade">
<Component />
</div>
</CSSTransition>
);
}}
</Route>
);
})}
</>
);
});
I am using react-transition-group v4.4.1.
Here is what I did and worked.
const { location } = this.props; // use with withRouter
const transitionKey = location.pathname;
<div className={classes.root}>
<TransitionGroup component={null}>
<CSSTransition
key={transitionKey}
classNames="slideLeftToRight"
addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
>
<Switch location={location}>
<Route path="/">
<div id="page 1" />
</Route>
<Route path="/another">
<div id="page 2" />
</Route>
</Switch>
</CSSTransition>
</TransitionGroup>
</div>
TransitionGroup looks at the transition key, and if there is a change in pathname, TransitionGroup will execute the transitioning between components.
Hey Jordan! I love your SandBox. I have a very specific use case that needs HashRouter, and I am using v6. I am trying to play with your code and get ur demo working in my case, but I am having difficulty getting the out transition to work. Is there any reason you can see this adaptation wouldn't work?
function StackNavigator() {
const location = useLocation();
const routeRefs = useRef<any>([]);
const currentKey = location.pathname.split("/")[1] || "/";
const isMatch = useCallback(
(path: string): boolean => {
return location.pathname === path ?? false;
},
[location],
);
return (
<Routes>
{tabRoutes.map(({ route, Element }, index) => {
return (
<Route
key={route}
path={route}
element={
<CSSTransition
key={currentKey}
nodeRef={routeRefs.current[index]}
in={isMatch(route)}
timeout={300}
classNames="fade"
unmountOnExit
appear
>
<div
ref={(ref) => (routeRefs.current[index] = ref)}
style={{ height: "100%", width: "100%" }}
className="fade"
>
<Element />
</div>
</CSSTransition>
}
></Route>
);
})}
</Routes>
);
}
It does seem as though the refs aren't having an effect, But I don't know why that would be.