Marcb7
Marcb7

Reputation: 109

How do I do exact redirect with Navigate in react router dom v6?

In the old version 5 of react router dom, I used 'Redirect' to do the route redirection, and the code of my application was this:

import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom';
import Navbar from './core/components/Navbar';
import Admin from './pages/Admin';
import Catalog from './pages/Catalog';
import ProductDetails from './pages/Catalog/components/ProductDetails';
import Home from './pages/Home';
// BrowserRouter vai encapsular toda a aplicação, ou seja, ele vai gerenciar todas as rotas disponíveis.
// O Switch vai decidir qual rota ele tem que renderizar.
// Através do componente Route é que vamos, de fato, definir a URL de cada rota na aplicação.

const Routes = () => (
    <BrowserRouter>
        <Navbar />
        <Switch>
            <Route path="/" exact>
                <Home />
            </Route>
            <Route path="/products" exact>
                <Catalog />
            </Route>
            <Route path="/products/:productId">
                <ProductDetails />
            </Route>
            <Redirect from="/admin" to="/admin/products" exact />
            <Route path="/admin">
                <Admin />
            </Route>
        </Switch>
    </BrowserRouter>
);

export default Routes;

The line <Redirect from="/admin" to="/admin/products" exact /> is so that, when I arrive at the /admin page, I will be taken to the page /admin/products automatically.

After updating react router dom to version 6, I made the project changes and now the code looks like this:

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import Navbar from './core/components/Navbar';
import Admin from './pages/Admin';
import Catalog from './pages/Catalog';
import ProductDetails from './pages/Catalog/components/ProductDetails';
import Home from './pages/Home';

const RoutesPages = () => (
    <BrowserRouter>
        <Navbar />
        <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/products" element={<Catalog />} />
            <Route path="/products/:productId" element={<ProductDetails />} />
            <Route path="/admin" element={<Navigate to="/admin/products" replace={true} />} />
            <Route path="/admin" element={<Admin />} />
        </Routes>
    </BrowserRouter>
);

export default RoutesPages;

Since 'exact' is no longer used in version 6, I'm having the problem of not displaying anything else on the '/admin/products' page, all elements disappeared (no links, navbar, and so on) because the 'exact' had the function of guaranteeing me to be on the '/admin' page, until redirecting me to /admin/products.

How do I resolve this?

............................

up:

I'm including two codes that will help you understand how the route is being rendered for the "/admin/products" path:

import { Route, Routes, } from "react-router-dom";
import Navbar from "./components/Navbar";
import Products from "./components/Products";
import './styles.scss';

const Admin = () => (
    <div className="admin-container">
        <Navbar />
        <div className="admin-content">
            <Routes>
                <Route path="/admin/products" element={<Products />} />
                <Route path="/admin/categories" element={<h1>Categories</h1>} />
                <Route path="/admin/users" element={<h1>Users</h1>} />
            </Routes>
        </div>
    </div>
);

export default Admin;
import { Route, Routes } from 'react-router-dom';
import Form from './Form';
import List from './List';

const Products = () => {
    return (
        <div>
            <Routes>
                <Route path="/admin/products" element={<List />} />
                <Route path="/admin/products/create" element={<Form />} />
                <Route path="/admin/products/:productId" element={<h1>Editar produto</h1>} />
            </Routes>
        </div>
    );
}

export default Products;

I've now added /* after /admin on script Routes.tsx:

const RoutesPages = () => (
    <BrowserRouter>
        <Navbar />
        <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/products" element={<Catalog />} />
            <Route path="/products/:productId" element={<ProductDetails />} />
            <Route path="/admin" element={<Navigate to="/admin/products" replace={true} />} />
            <Route path="/admin/*" element={<Admin />} />
        </Routes>
    </BrowserRouter>
);

export default RoutesPages;

Upvotes: 2

Views: 2334

Answers (1)

Drew Reese
Drew Reese

Reputation: 203051

So it seems it is the route rendering the List component you want rendered when the user navigates to "/admin", i.e. the route rendering on path "/admin/products".

The root admin route is correctly rendering a "*" wildcard suffix to allow matching additional sub-routes. The Admin component rendering the "/products" sub-route also needs to render a "*" wildcard suffix to match further nested sub-routes.

The RoutesPages component should render the root routes with trailing "*" character to allow matching sub-routes.

const RoutesPages = () => (
  <>
    <Navbar />
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/products/*" element={<Catalog />} />
      <Route path="/admin/*" element={<Admin />} /> // match sub-routes
    </Routes>
  </>
);

Then the Admin component can render an index route to redirect to the "/products" sub-route and append a trailing "*" character to the "/products/*" path to allow additional sub-route matching.

const Admin = () => (
  <div className="admin-container">
    <Navbar />
    <div className="admin-content">
      <Routes>
        <Route index element={<Navigate to="products" replace />} /> // redirect to desired path
        <Route path="/products/*" element={<Products />} /> // match sub-routes
        <Route path="/categories" element={<h1>Categories</h1>} />
        <Route path="/users" element={<h1>Users</h1>} />
      </Routes>
    </div>
  </div>
);

...

const Products = () => {
  return (
    <div>
      <Routes>
        <Route index element={<List />} /> // desired path/component
        <Route path="/create" element={<Form />} />
        <Route path="/:productId" element={<h1>Editar produto</h1>} />
      </Routes>
    </div>
  );
};

Edit how-do-i-do-exact-redirect-with-navigate-in-react-router-dom-v6

Upvotes: 1

Related Questions