1

How can I protect routes with the react router dom v6 library? I am creating my first application with reactjs, I would like to know how I can protect routes, in this case all routes found in / dashboard / in this area can only enter users who have credentials, that is, who are registered.

Original post: https://stackoverflow.com/a/69870303/17222061

Error: PrivateRoute(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

Public routes (anyone can see these pages)

  • http://localhost:3000/
  • http://localhost:3000/register
  • http://localhost:3000/login

Private routes (when user log in):

  • http://localhost:3000/dashboard/
  • http://localhost:3000/dashboard/accounting
  • http://localhost:3000/dashboard/employee
  • http://localhost:3000/dashboard/ecommerce

package.json

"react-router-dom": "^6.0.1",

Index.js

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App";

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);

App.js

import AppRouter from "./routers/AppRouter";
import "./css/main.css";

function App() {
  return (
    <>
      <AppRouter />
    </>
  );
}

export default App;

AppRouter

import { Route, Routes } from "react-router-dom";
import HomeView from "../components/views/public/HomeView";
import LoginView from "../components/views/public/LoginView";
import NotFound from "../components/views/public/NotFound";
import RegisterView from "../components/views/public/RegisterView";
import DashboardRoutes from "./DashboardRoutes";
import PrivateRoute from "./PrivateRoute";

const AppRouter = () => {
  return (
    <div>
      <Routes>
        {/* Public routes: */}
        <Route path="/" element={<HomeView />} />
        <Route path="/login" element={<LoginView />} />
        <Route path="/register" element={<RegisterView />} />
        {/* Private routes: */}
        <Route
          path="dashboard/*"
          element={
            <PrivateRoute>
              <DashboardRoutes />
            </PrivateRoute>
          }
        />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </div>
  );
};
export default AppRouter;

DashboardRoutes

import { Routes, Route } from "react-router-dom";
import AccountingHomeView from "../components/views/accounting/AccountingHomeView";
import DashboardHomeView from "../components/views/dashboard/DashboardHomeView";
import EcommerceHomeView from "../components/views/ecommerce/EcommerceHomeView";
import EmployeeHomeView from "../components/views/employee/EmployeeHomeView";
import NotFound from "../components/views/public/NotFound";

const DashboardRoutes = function () {
  return (
    <>
      <Routes>
        <Route path="/" element={<DashboardHomeView />} />
        <Route path="accounting" element={<AccountingHomeView />} />
        <Route path="employee" element={<EmployeeHomeView />} />
        <Route path="ecommerce" element={<EcommerceHomeView />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </>
  );
};

export default DashboardRoutes;

PrivateRoute (Logic here)

import { Navigate } from "react-router-dom";

const PrivateRoute = function ({ children }) {
  // True or False to emulated login or logout user
  let isAuthenticated = false;
  if (isAuthenticated) {
    return children;
  } else {
    <Navigate to="/login" />;
  }
};

export default PrivateRoute;

Error: PrivateRoute(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.

Emma R.
  • 69
  • 7

1 Answers1

1

You need to return valid JSX from PrivateRoute, i.e. return <Navigate to="/login" replace />;.

const PrivateRoute = function ({ children }) {
  // True or False to emulated login or logout user
  let isAuthenticated = false;
  if (isAuthenticated) {
    return children;
  } else {
    return <Navigate to="/login" replace />; // <-- return the redirect
  }
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Thanks!, what is replace used for? – Emma R. Nov 15 '21 at 13:40
  • 1
    @EmmaR. It indicates if you want the navigation to be a PUSH or REPLACE navigation, in other words, if it is a regular navigation that *pushes* a new path onto the history stack, or if it should be a redirect and *replace* the current entry on the history stack. – Drew Reese Nov 15 '21 at 15:58