2

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...

brspnnng
  • 41
  • 1
  • 4

0 Answers0