I need to create some transitions and have a scenario in which the Child which is transitioned "in" should have a notion about its transition state.
What i try to do is set a "transitionDone" state to "false" right before the transition and after the transition is finished i update this state to "true".
But if i go through the different routes, the sequel transition gets "transitionDone:true" immediately when it mounts, but i want it to be false so i can tell the component that it is done transitioning.
A simplified example
Parent component
import {
BrowserRouter as Router,
Switch,
Route,
useLocation
} from "react-router-dom";
import { useEffect, useState, useRef } from "react";
import Chapter from "./Chapter";
import { Transition, SwitchTransition } from "react-transition-group";
//
function Content() {
const location = useLocation();
const [transitionDone, setTransitionDone] = useState(false);
const promiseRef = useRef(Promise.resolve(true));
// OnEnter Transition
let onEnter = (node) => {
setTransitionDone(false);
console.log("Parent: transition start");
// perform the transition and the resolve
// imagine an transition which takes 500ms
promiseRef.current = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("enter");
}, 500);
});
};
// OnExit Transition
let onExit = (node) => {
promiseRef.current = new Promise((resolve, reject) => {
resolve("exit");
});
};
//
let endListener = (node, done) => {
//
promiseRef.current
.then((type) => {
// check if this is the enter transition
if (type === "enter") {
console.log("Parent: transition done");
setTransitionDone(true);
}
return;
})
.then(done);
};
return (
<div className="content">
<SwitchTransition mode="in-out">
<Transition
key={location.pathname}
onEnter={onEnter}
onExit={onExit}
addEndListener={endListener}
>
<div>
<Switch location={location}>
<Route path="/:chapterSlug">
<Chapter transitionDone={transitionDone}></Chapter>
</Route>
</Switch>
</div>
</Transition>
</SwitchTransition>
</div>
);
}
export default Content;
Child component
import { useParams } from "react-router-dom";
import { useEffect } from "react";
export default function Chapter(props) {
const { transitionDone } = props;
const { chapterSlug } = useParams();
useEffect(() => {
console.log(`Child: mount, transitionDone: ${transitionDone}`);
}, []);
useEffect(() => {
console.log(`Child: transitionDone changed ${transitionDone}`);
}, [transitionDone]);
return <div className="chapter">Chapter: {chapterSlug}</div>;
}
I also made a sandbox example https://codesandbox.io/s/late-microservice-83e0y?file=/src/Chapter.js:0-476
If you click on Chapter 01 the console will show:
- Parent: transition start
- Child: mount, transitionDone: false
- Child: transitionDone changed false
- Parent: transition done
- Child: transitionDone changed true
This is what i want, because the child component has a false transitionDone when it mounts. But if i click on Chapter 02:
- Parent: transition start
- Child: mount, transitionDone: true
- Child: transitionDone changed true
- Child: transitionDone changed false
- Parent: transition done
- Child: transitionDone changed true
When the child mounts it already has transitionDone true...