Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ahmadrasyidsalim/4f573019eb05cf17c78cf36298d0f443 to your computer and use it in GitHub Desktop.
Save ahmadrasyidsalim/4f573019eb05cf17c78cf36298d0f443 to your computer and use it in GitHub Desktop.

Revisions

  1. @mjackson mjackson revised this gist Nov 9, 2021. No changes.
  2. @mjackson mjackson revised this gist Nov 5, 2021. 1 changed file with 17 additions and 1 deletion.
    18 changes: 17 additions & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -139,4 +139,20 @@ The `<Navigate replace>` prop tells the router to use `history.replaceState()` w

    You can prepare your React Router v5 app for v6 by replacing any `<Redirect>` elements you may be rendering inside a `<Switch>` with custom redirect logic in your server's request handler.

    Then, you can stop using the `<StaticRouter context>` API and forget about checking the `context` object after rendering because you know that all of your redirects have already been taken care of.
    Then, you can stop using the `<StaticRouter context>` API and forget about checking the `context` object after rendering because you know that all of your redirects have already been taken care of.

    If you want to redirect client-side, move your `<Redirect>` into a `<Route render>` prop.

    ```tsx
    // Change this:
    <Switch>
    <Redirect from="about" to="about-us" />
    </Switch>

    // to this:
    <Switch>
    <Route path="about" render={() => <Redirect to="about-us" />} />
    </Switch>
    ```

    Normal `<Redirect>` elements that are not inside a `<Switch>` are ok to remain. They will become `<Navigate>` elements in v6.
  3. @mjackson mjackson revised this gist Oct 14, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -86,7 +86,7 @@ This will ensure that both:
    - search engine crawlers can see the redirect and avoid indexing the redirected page and
    - you don't waste any more resources server rendering than you have to

    ## Configuring Redirects on Static Hosting Providers
    ## Configuring Static Hosting Providers

    Many static hosting providers give you an easy way to configure redirects so you can still get good SEO even on a static site with no server. See the docs on various providers below:

  4. @mjackson mjackson revised this gist Oct 14, 2021. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -133,4 +133,10 @@ Please note however that *this won't work when server rendering* because the nav

    The new `<Navigate>` element in v6 works like a declarative version of the `useNavigate()` hook. It's particularly handy in situations where you need a React element to declare your navigation intent, like `<Route element>`. It also replaces any uses that you had for a `<Redirect>` element in v5 **outside** of a `<Switch>`.

    The `<Navigate replace>` prop tells the router to use `history.replaceState()` when updating the URL so the `/` entry won't end up in the history stack. This means that when someone clicks the back button, they'll end up at the page they were at before they navigated to `/`.
    The `<Navigate replace>` prop tells the router to use `history.replaceState()` when updating the URL so the `/` entry won't end up in the history stack. This means that when someone clicks the back button, they'll end up at the page they were at before they navigated to `/`.

    ## Get Started Upgrading Today

    You can prepare your React Router v5 app for v6 by replacing any `<Redirect>` elements you may be rendering inside a `<Switch>` with custom redirect logic in your server's request handler.

    Then, you can stop using the `<StaticRouter context>` API and forget about checking the `context` object after rendering because you know that all of your redirects have already been taken care of.
  5. @mjackson mjackson revised this gist Oct 14, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -131,6 +131,6 @@ Please note however that *this won't work when server rendering* because the nav

    ## Notes on the `<Navigate>` API

    The new `<Navigate>` element in v6 works like a declarative version of the `useNavigate()` hook. It's particularly handy in situations where you need a React element to declare your navigation intent, like `<Route element>`.
    The new `<Navigate>` element in v6 works like a declarative version of the `useNavigate()` hook. It's particularly handy in situations where you need a React element to declare your navigation intent, like `<Route element>`. It also replaces any uses that you had for a `<Redirect>` element in v5 **outside** of a `<Switch>`.

    The `<Navigate replace>` prop tells the router to use `history.replaceState()` when updating the URL so the `/` entry won't end up in the history stack. This means that when someone clicks the back button, they'll end up at the page they were at before they navigated to `/`.
  6. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -91,6 +91,7 @@ This will ensure that both:
    Many static hosting providers give you an easy way to configure redirects so you can still get good SEO even on a static site with no server. See the docs on various providers below:

    - [AWS S3 Bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-page-redirect.html)
    - [Cloudflare Pages](https://developers.cloudflare.com/pages/platform/redirects)
    - [Netlify](https://docs.netlify.com/routing/redirects/)
    - [Vercel](https://vercel.com/docs/cli#project-configuration/redirects)
    - [Firebase Hosting](https://firebase.google.com/docs/hosting/full-config#redirects)
  7. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -47,6 +47,11 @@ So we are rethinking our redirect strategy in React Router v6 to avoid these pro

    Our recommendation for redirecting in React Router v6 really doesn't have much to do with React or React Router at all. It is simply this: **if you need to redirect, do it on the server before you render any React and send the right status code**. That's it.

    If you do this, you'll get:

    - better SEO for redirected URLs and
    - faster responses from your web server

    To handle the situation above, your server code might look something like this (using the Express API):

    ```tsx
  8. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -58,7 +58,7 @@ import App from "./App";

    function handleExpressRequest(req, res) {
    // Handle redirects *before* you render and save yourself some time.
    // Bonus: Send a real 302 HTTP status code so crawlers don't index
    // Bonus: Send a HTTP 302 Found status code so crawlers don't index
    // this page!
    if (req.url === "/") {
    return res.redirect("/home");
  9. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -71,7 +71,7 @@ function handleExpressRequest(req, res) {
    </StaticRouter>
    );

    // ... and send a HTTP 20 OK status code so crawlers index the page.
    // ...and send a HTTP 200 OK status code so crawlers index the page.
    res.end(html);
    }
    ```
  10. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,9 @@ import { StaticRouter } from "react-router-dom/server";
    import App from "./App";

    function handleExpressRequest(req, res) {
    // Handle redirects *before* you render and save yourself some time!
    // Handle redirects *before* you render and save yourself some time.
    // Bonus: Send a real 302 HTTP status code so crawlers don't index
    // this page!
    if (req.url === "/") {
    return res.redirect("/home");
    }
    @@ -69,6 +71,7 @@ function handleExpressRequest(req, res) {
    </StaticRouter>
    );

    // ... and send a HTTP 20 OK status code so crawlers index the page.
    res.end(html);
    }
    ```
  11. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -78,7 +78,7 @@ This will ensure that both:
    - search engine crawlers can see the redirect and avoid indexing the redirected page and
    - you don't waste any more resources server rendering than you have to

    ## Configuring Static Hosting Providers
    ## Configuring Redirects on Static Hosting Providers

    Many static hosting providers give you an easy way to configure redirects so you can still get good SEO even on a static site with no server. See the docs on various providers below:

  12. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 27 additions and 1 deletion.
    28 changes: 27 additions & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,33 @@ function handleExpressRequest(req, res) {
    }
    ```

    This will ensure that both a) search engine crawlers can see the redirect and avoid indexing the redirected page and b) you don't waste any more time server rendering than you have to.
    This will ensure that both:

    - search engine crawlers can see the redirect and avoid indexing the redirected page and
    - you don't waste any more resources server rendering than you have to

    ## Configuring Static Hosting Providers

    Many static hosting providers give you an easy way to configure redirects so you can still get good SEO even on a static site with no server. See the docs on various providers below:

    - [AWS S3 Bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/how-to-page-redirect.html)
    - [Netlify](https://docs.netlify.com/routing/redirects/)
    - [Vercel](https://vercel.com/docs/cli#project-configuration/redirects)
    - [Firebase Hosting](https://firebase.google.com/docs/hosting/full-config#redirects)
    - [surge.sh](https://surge.sh/help/adding-redirects)

    On static hosting providers that don't provide a way to do redirects on the server (e.g. GitHub Pages), you can still improve SEO by serving a page with the the redirect encoded in the page's metadata, like this:

    ```html
    <!doctype html>
    <title>Redirecting to https://example.com/home</title>
    <meta http-equiv="refresh" content="0; URL=https://example.com/home">
    <link rel="canonical" href="https://example.com/home">
    ```

    The `<meta>` tag tells the browser where to go, and the `<link>` tag tells crawlers to use that page as the "canonical" representation for that page, which allows you to [consolidate duplicate URLs](https://developers.google.com/search/docs/advanced/crawling/consolidate-duplicate-urls) for Googlebot.

    ## Not Server Rendering

    If you aren't server rendering your app you can still redirect on the initial render in the client like this:

  13. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -62,6 +62,7 @@ function handleExpressRequest(req, res) {
    return res.redirect("/home");
    }

    // If there aren't any redirects to process, go ahead and render...
    let html = ReactDOMServer.renderToString(
    <StaticRouter location={req.url}>
    <App />
  14. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -72,6 +72,8 @@ function handleExpressRequest(req, res) {
    }
    ```

    This will ensure that both a) search engine crawlers can see the redirect and avoid indexing the redirected page and b) you don't waste any more time server rendering than you have to.

    If you aren't server rendering your app you can still redirect on the initial render in the client like this:

    ```tsx
  15. @mjackson mjackson revised this gist Oct 13, 2021. No changes.
  16. @mjackson mjackson revised this gist Oct 13, 2021. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    # Redirects in React Router v6

    An important part of "routing" is handling redirects. Redirects usually happen when you want to preserve an old link and send all the traffic bound for that destination to some new URL so you don't end up with broken links.

    The way we recommend handling redirects has changed in React Router v6. This document explains why.
    @@ -41,7 +43,7 @@ As mentioned above, there are a few problems with our redirect strategy in React

    So we are rethinking our redirect strategy in React Router v6 to avoid these problems.

    ## Redirects in React Router v6
    ## Handling Redirects in React Router v6

    Our recommendation for redirecting in React Router v6 really doesn't have much to do with React or React Router at all. It is simply this: **if you need to redirect, do it on the server before you render any React and send the right status code**. That's it.

  17. @mjackson mjackson created this gist Oct 13, 2021.
    96 changes: 96 additions & 0 deletions redirects-in-react-router-v6.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    An important part of "routing" is handling redirects. Redirects usually happen when you want to preserve an old link and send all the traffic bound for that destination to some new URL so you don't end up with broken links.

    The way we recommend handling redirects has changed in React Router v6. This document explains why.

    ## Background

    In React Router v4/5 (they have the same API, you can read about why we had to bump the major version [here](https://reacttraining.com/blog/react-router-v5/#why-the-major-version-bump)) we had a `<Redirect>` component that you could use to tell the router when to automatically redirect to another URL. You might have used it like this:

    ```tsx
    import { Switch, Route, Redirect } from "react-router-dom";

    function App() {
    return (
    <Switch>
    <Route path="/home">
    <HomePage />
    </Route>
    <Redirect from="/" to="/home" />
    </Switch>
    );
    }
    ```

    In React Router v4/5, when the user lands at the `/` URL in the app above, they are automatically redirected to `/home`.

    There are two common environments in which React Router usually runs:

    - In the browser
    - On the server using React's node.js API

    In the browser a `<Redirect>` is simply a `history.replaceState()` on the initial render. The idea is that when the page loads, if you're at the wrong URL, just change it and rerender so you can see the right page. This gets you to the right page, but also has some issues as we'll see later.

    On the server you handle redirects by passing an object to `<StaticRouter context>` when you render. Then, you check `context.url` and `context.status` after the render to see if a `<Redirect>` was rendered somewhere in the tree. This generally works fairly well, except you have to invoke `ReactDOMServer.renderToString(...)` just to know if you need to redirect, which is less than ideal.

    ## Problems

    As mentioned above, there are a few problems with our redirect strategy in React Router v4/5, namely:

    - "Redirecting" in the browser isn't really redirecting. Your server still served up a valid HTML page with a 200 status code at the URL originally requested by the client. If that client was a search engine crawler, it got a valid HTML page and assumes it should index the page. It doesn't know anything about the redirect because the page was served with a 200 OK status code. This hurts your SEO for that page.
    - Invoking `ReactDOMServer.renderToString()` on the server just to know if you need to redirect or not wastes precious resources and time. Redirects can always be known ahead of time. You shouldn't need to render to know if you need to redirect or not.

    So we are rethinking our redirect strategy in React Router v6 to avoid these problems.

    ## Redirects in React Router v6

    Our recommendation for redirecting in React Router v6 really doesn't have much to do with React or React Router at all. It is simply this: **if you need to redirect, do it on the server before you render any React and send the right status code**. That's it.

    To handle the situation above, your server code might look something like this (using the Express API):

    ```tsx
    import * as React from "react";
    import * as ReactDOMServer from "react-dom/server";
    import { StaticRouter } from "react-router-dom/server";

    import App from "./App";

    function handleExpressRequest(req, res) {
    // Handle redirects *before* you render and save yourself some time!
    if (req.url === "/") {
    return res.redirect("/home");
    }

    let html = ReactDOMServer.renderToString(
    <StaticRouter location={req.url}>
    <App />
    </StaticRouter>
    );

    res.end(html);
    }
    ```

    If you aren't server rendering your app you can still redirect on the initial render in the client like this:

    ```tsx
    import { Routes, Route, Navigate } from "react-router-dom";

    function App() {
    return (
    <Routes>
    <Route path="/home" element={<Home />} />
    <Route path="/" element={<Navigate replace to="/home" />} />
    </Routes>
    );
    }
    ```

    In the above example, when someone visits `/`, they will automatically be redirected to `/home`, same as before.

    Please note however that *this won't work when server rendering* because the navigation happens in a `React.useEffect()`.

    ## Notes on the `<Navigate>` API

    The new `<Navigate>` element in v6 works like a declarative version of the `useNavigate()` hook. It's particularly handy in situations where you need a React element to declare your navigation intent, like `<Route element>`.

    The `<Navigate replace>` prop tells the router to use `history.replaceState()` when updating the URL so the `/` entry won't end up in the history stack. This means that when someone clicks the back button, they'll end up at the page they were at before they navigated to `/`.