Error: [PrivateRoute] no es un componente. Todos los hijos componentes de debe ser un o

5 minutos de lectura

avatar de usuario
porque me odio a mi mismo

Estoy usando React Router v6 y estoy creando rutas privadas para mi aplicación.

En archivo PrivateRoute.jstengo el código

import React from 'react';
import {Route,Navigate} from "react-router-dom";
import {isauth}  from 'auth'

function PrivateRoute({ element, path }) {
  const authed = isauth() // isauth() returns true or false based on localStorage
  const ele = authed === true ? element : <Navigate to="/Home"  />;
  return <Route path={path} element={ele} />;
}

export default PrivateRoute

y en archivo ruta.js He escrito como:

 ...
<PrivateRoute exact path="/" element={<Dashboard/>}/>
<Route exact path="/home" element={<Home/>}/>

He pasado por el mismo ejemplo. Ejemplo de autenticación de React-router – StackBlitz, archivo App.tsx

¿Se me escapa algo?

avatar de usuario
dibujó reese

Solamente Route los componentes pueden ser hijos de Routes. Si sigue los documentos de v6, verá que el patrón de autenticación es usar un componente contenedor para manejar la verificación de autenticación y la redirección.

function RequireAuth({ children }: { children: JSX.Element }) {
  let auth = useAuth();
  let location = useLocation();

  if (!auth.user) {
    // Redirect them to the /login page, but save the current location they were
    // trying to go to when they were redirected. This allows us to send them
    // along to that page after they login, which is a nicer user experience
    // than dropping them off on the home page.
    return <Navigate to="/login" state={{ from: location }} />;
  }

  return children;
}

...

<Route
  path="/protected"
  element={
    <RequireAuth>
      <ProtectedPage />
    </RequireAuth>
  }
/>

El antiguo patrón v5 de crear personalizado Route los componentes ya no funcionan. Un patrón v6 actualizado usando su código/lógica podría tener el siguiente aspecto:

const PrivateRoute = ({ children }) => {
  const authed = isauth() // isauth() returns true or false based on localStorage
  
  return authed ? children : <Navigate to="/Home" />;
}

y para usar

<Route
  path="/dashboard"
  element={
    <PrivateRoute>
      <Dashboard />
    </PrivateRoute>
  }
/>

  • La respuesta de Dallin es buena, pero para ser honesto, no le ahorra mucho más que simplemente envolver el componente de destino con un componente de autenticación. En todo caso, es una solución más compleja ya que ahora implica renderizar dos Route componentes y un Outlet solo para representar una sola ruta.

    – Drew Reese

    7 de noviembre de 2021 a las 6:49


  • Gracias, esta fue mi solución y funcionó.

    – Porque me odio a mi mismo

    7 de noviembre de 2021 a las 13:44

  • @DrewReese, creo que la ventaja de la respuesta de Dallin entra en juego cuando tienes muchas rutas que necesitan protección. Entonces, con solo una ruta protegida, sí, realmente no tiene ningún sentido, pero ¿qué pasa con 5 o 20? Comienza a ahorrar al no requerir un montón de componentes de envoltura redundantes.

    – MikeyT

    6 de enero a las 7:38

  • @MikeyT Totalmente de acuerdo, vea los comentarios debajo de su respuesta. Inicialmente, el mío se tomó directamente de los documentos oficiales, para proteger un solo componente. Al abordar este tipo de preguntas, normalmente cubro ambos casos de uso ahora.

    – Drew Reese

    6 ene a las 16:17

  • Funcionó para mí, solo tuve que cambiar const Private = (Component) => a constante Private = ({Component}) =>

    –Daniel Miranda

    27 de enero a las 2:36


avatar de usuario
JLarky

Sé que esta no es exactamente la receta cómo hacer PirvateRoute funciona, pero solo quería mencionar que los nuevos documentos recomiendan un enfoque ligeramente diferente para manejar este patrón con react-router v6:

    <Route path="/protected" element={<RequireAuth><ProtectedPage /></RequireAuth>} />
import { Navigate, useLocation } from "react-router";

export const RequireAuth: React.FC<{ children: JSX.Element }> = ({ children }) => {
  let auth = useAuth();
  let location = useLocation();

  if (!auth.user) {
    return <Navigate to="/login" state={{ from: location }} />;
  }

  return children;
};

y se supone que debes agregar más rutas dentro ProtectedPage mismo si lo necesita.

Ver documentos y ejemplo para más detalles. Además, verifique esta nota por Michael Jackson que entra en algunos detalles de implementación.

avatar de usuario
cansu

Simplemente configure el componente de su enrutador en elemento prop:

<Routes>
  <Route exact path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
  <Route path="/dashboard" element={<Dashboard />} />
</Routes>

También puede verificar la actualización desde v5,
https://reactrouter.com/docs/en/v6/upgrading/v5

avatar de usuario
mapa815

Si está utilizando un segundo archivo para trabajar en su index.js. Aquí hay un fragmento de código más simple que puede ayudar a otros a entender mejor. Es bastante sencillo y no necesita “exacto” y “cambiar” para cambiar entre las rutas gracias a la nueva versión.

índice.js

import React from "react";
import ReactDOM from "react-dom";

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

import "./index.css";
import App from "./App";

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

Aplicación.js

Tenga en cuenta que debe importar { Rutas, Ruta } en lugar de { Ruta } (como estaba en versiones anteriores). Además, tenga en cuenta que en el archivo App.js, no es necesario volver a importar BrowserRouter.

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

import AllPages from "./pages/AllPages";
import NewContactsPage from "./pages/ContactsPage";
import FavoritesPage from "./pages/Favorites";

function App() {

  return (
    <div>
      <Routes>
        <Route path="/" element={<AllPages />} />
        <Route path="/new-contacts" element={<NewContactsPage />} />
        <Route path="/favorites" element={<FavoritesPage />} />
      </Routes>
    </div>
  );
}

export default App;

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad