React-Router v6: Animated Transitions DIY
Tags: todayilearned, react, reactrouter, animation
Published: 2022-03-25 17:31:22

Thanks to [Anxin.Y](https://dev.to/anxiny) for [the post](https://dev.to/anxiny/react-router-animated-transitions-diy-4opd) about making a transition DIY through animation on React-router v5. 

Now, I will try to make it with v6.

## So, Let's start!
First, let's create the App component:

```
export default function App() {
  return (
    <BrowserRouter>
      <div className={`App`}>
        <nav>
          <Link to="/">Home</Link>
          <Link to="/other">Other</Link>
        </nav>
        <Content />
      </div>
    </BrowserRouter>
  );
}
```
Then, the Content component:

```
function Content() {
    return (
    <div>
      <Routes>
        <Route path="/" element={<section>Home</section>} />
        <Route path="/other" element={<section>Other</section>} />
      </Routes>
    </div>
  );
}

```
Now, we need to stop route from switching. By default, the `<Routes />` (in v5, `<Switch />`) will use the current url for matching the route, but we can stop it from doing that by assigning it a Location.

```
<Routes location={displayLocation}>
```
We will need a state to keep the current location before 'Out' animation finish, and we can assign the current location as the default value. we can use useLocation to get the current location.

```
  ...
  const location = useLocation();
  const [displayLocation, setDisplayLocation] = useState(location);
  ...
  <Routes location={displayLocation}>
```
Now, if you click the Link, you will notice that even the URL is changed, the content stay the same.

Next, we need add a state for controlling the stage of the transition.

```
const [transitionStage, setTransistionStage] = useState("fadeIn");
```
Then, we can use useEffect to check if location is changed, and start the 'fadeOut'.

```
  useEffect(() => {
    if (location !== displayLocation) setTransistionStage("fadeOut");
  }, [location, displayLocation]);
```
Finally, we need a way to update the stage and location when animation is over. For that we can use the onAnimationEnd event.

```
function Content() {
  ...
  return (
    <div
      className={`${transitionStage}`}
      onAnimationEnd={() => {
        if (transitionStage === "fadeOut") {
          setTransistionStage("fadeIn");
          setDisplayLocation(location);
        }
      }}
    >
      ...
    </div>
  );
}
```
Before completion, You must add these to your CSS:

```
.fadeIn {
  animation: 0.5s fadeIn forwards;
}

.fadeOut {
  animation: 0.5s fadeOut forwards;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translate(-20px, 0);
  }
  to {
    opacity: 1;
    transform: translate(0px, 0px);
  }
}

@keyframes fadeOut {
  from {
    opacity: 1;
    transform: translate(0px, 0px);
  }
  to {
    transform: translate(-20px, 0);
    opacity: 0;
  }
}
```

And, Here is the demo and the finished code:

{% codesandbox x6299o %}

```
import { useState, useEffect } from "react";
import {
  BrowserRouter,
  Link,
  useLocation,
  Route,
  Routes
} from "react-router-dom";
import "./styles.css";

export default function App() {
  return (
    <BrowserRouter>
      <div className={`App`}>
        <nav>
          <Link to="/">Home</Link>
          <Link to="/other">Other</Link>
        </nav>
        <Content />
      </div>
    </BrowserRouter>
  );
}

function Content() {
  const location = useLocation();

  const [displayLocation, setDisplayLocation] = useState(location);
  const [transitionStage, setTransistionStage] = useState("fadeIn");

  useEffect(() => {
    if (location !== displayLocation) setTransistionStage("fadeOut");
  }, [location, displayLocation]);

  return (
    <div
      className={`${transitionStage}`}
      onAnimationEnd={() => {
        if (transitionStage === "fadeOut") {
          setTransistionStage("fadeIn");
          setDisplayLocation(location);
        }
      }}
    >
      <Routes location={displayLocation}>
        <Route path="/" element={<section>Home</section>} />
        <Route path="/other" element={<section>Other</section>} />
      </Routes>
    </div>
  );
}
```
Thank you [AnxinYang](https://dev.to/anxiny)!