React

React

Tutorial React: Nuevos métodos create de React Router

React: aprende a usar los nuevos métodos createBrowserRouter, createHashRouter y createMemoryRouter de React Router para mejorar la navegación en tus aplicaciones.

Aprende React y certifícate

Principales cambios en React Router

React Router v6.4 introduce varios cambios significativos respecto a versiones anteriores. Estos cambios están diseñados para mejorar la experiencia de desarrollo y la eficiencia en la navegación dentro de aplicaciones React.

Nuevos métodos create: Uno de los cambios más importantes es la introducción de los métodos createBrowserRouter, createHashRouter y createMemoryRouter. Estos métodos proporcionan una forma más directa y flexible de configurar el enrutamiento en lugar de usar los componentes BrowserRouter, HashRouter y MemoryRouter tradicionales. Por ejemplo, createBrowserRouter permite definir rutas y su configuración directamente en el archivo de enrutamiento, lo que facilita la gestión y lectura del código.

Método createBrowserRouter

El método createBrowserRouter es una de las nuevas incorporaciones en React Router v6.4 Este método proporciona una forma más directa y flexible de configurar el enrutamiento en aplicaciones React, reemplazando el uso del componente tradicional BrowserRouter.

Configuración básica

El uso de createBrowserRouter implica definir las rutas y su configuración directamente en el archivo de enrutamiento, lo que facilita la gestión y lectura del código. Aquí hay un ejemplo básico de cómo configurar un enrutador con createBrowserRouter:

// router.jsx
import { createBrowserRouter } from 'react-router-dom';
import Layout from './pages/Layout/Layout';
import Home from './pages/Home/Home';
import About from './pages/About/About';

const router = createBrowserRouter([
  {
    element: <Layout />,
    children: [
      {
        path: '/',
        element: <Home />,
      },
      {
        path: 'about',
        element: <About />,
      },
    ]
  }
]);

export default router
// Layout.jsx
import { NavLink, Outlet } from "react-router-dom";

export default function Layout() {
  return (
    <>
      <header>
        <nav>
          <NavLink to="/">Home</NavLink>
          <NavLink to="/about">Perfil de usuario</NavLink>
        </nav>
      </header>
      <Outlet />
    </>
  );
}
// main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from 'react-router-dom';
import router from './router';

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)

Uso de createBrowserRouter en lugar de BrowserRouter: Aunque BrowserRouter sigue siendo funcional, se recomienda el uso de createBrowserRouter para una mayor flexibilidad y control.

Manejo de errores en rutas

La nueva versión incluye mejores mecanismos para manejar errores de enrutamiento, permitiendo definir rutas de error de manera más sencilla y clara. Esto se puede hacer directamente en la configuración de rutas:

// router.jsx
import { createBrowserRouter } from 'react-router-dom';
import Home from './pages/Home/Home';
import NotFound from './pages/NotFound/NotFound';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    errorElement: <NotFound />, // Elemento a renderizar en caso de error
  },
  // otras rutas...
]);

export default router

Data loaders y acciones

Una de las características más importantes de createBrowserRouter es su capacidad para manejar datos y acciones de manera eficiente. Esto se logra a través de las propiedades loader y action, que permiten realizar operaciones asíncrona directamente en la definición de las rutas.

// router.jsx
import { createBrowserRouter } from 'react-router-dom';
import Home from './pages/Home/Home';
import Login, { loginAction } from './pages/Login/Login';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    loader: async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const todo = await response.json();
      return todo;
    },
  },
  {
    path: 'login',
    element: <Login />,
    action: loginAction,
  },
]);

export default router
// main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from 'react-router-dom';
import router from './router';

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)

useLoaderData y useActionData: Nuevos hooks para acceder a los datos cargados por loaders y actions dentro de los componentes de la ruta.

Ejemplo usando useLoaderData:

// Home.jsx
import { useLoaderData } from "react-router-dom";
export default function Home() {
  const data = useLoaderData();

  return (
    <div>
      <h1>Home Page</h1>
      <ul>
        <li>ID: <span>{data.id}</span></li>
        <li>User ID: <span>{data.userId}</span></li>
        <li>Title: <span>{data.title}</span></li>
        <li>Completed: <span>{data.completed}</span></li>
      </ul>
    </div>
  )
}

Ejemplo de useActionData:

// Login.jsx
import { Form, redirect, useActionData, } from "react-router-dom";

export default function Login() {
  const errors = useActionData();

  return (
    <div>
      <h1>Inicio de sesión</h1>
      <Form method="post">
        <label>
          Email
          <input type="text" name="email" />
          {errors?.email && <small>{errors.email}</small>}
        </label>
        <br />
        <label>
          Password
          <input type="password" name="password" />
          {errors?.password && <small>{errors.password}</small>}
        </label>
        <br />
        <button type="submit">Sign up</button>
      </Form>
    </div>
  );
}

export async function loginAction({ request }) {
  const formData = await request.formData();
  const email = formData.get("email");
  const password = formData.get("password");
  const errors = {};

  // validate the fields
  if (typeof email !== "string" || !email.includes("@")) {
    errors.email =
      "That doesn't look like an email address";
  }

  if (typeof password !== "string" || password.length < 6) {
    errors.password = "Password must be > 6 characters";
  }

  // return data if we have errors
  if (Object.keys(errors).length) {
    return errors;
  }

  // otherwise login the user and redirect
  console.log("Login successful");
  return redirect("/");
}

Definición de rutas en JSX

La función createRoutesFromElements permite definir rutas directamente en JSX, lo que hace que la definición de rutas sea más declarativa y fácil de entender.

// router.jsx
import { createBrowserRouter, createRoutesFromElements, Route } from 'react-router-dom';
import Home from './pages/Home/Home';
import About from './pages/About/About';

const router = createBrowserRouter(
  createRoutesFromElements(
    <>
      <Route path="/" element={<Home />} />
      <Route path="about" element={<About />} />
    </>
  )
);

export default router
// main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from 'react-router-dom';
import router from './router';

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)

Carga diferida de componentes

React Router v6.4 facilita la integración con Suspense y lazy para cargar componentes de manera diferida, mejorando el rendimiento de la aplicación. Por ejemplo:

// router.jsx
import { lazy, Suspense } from 'react';
import { createBrowserRouter } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home/Home'));
const About = lazy(() => import('./pages/About/About'));
const NotFound = lazy(() => import('./pages/NotFound/NotFound'));

const router = createBrowserRouter([
  {
    path: '/',
    element: (
      <Suspense fallback={<div>Loading...</div>}>
        <Home />
      </Suspense>
    ),
  },
  {
    path: 'about',
    element: (
      <Suspense fallback={<div>Loading...</div>}>
        <About />
      </Suspense>
    ),
  },
  {
    path: '*',
    element: (
      <Suspense fallback={<div>Loading...</div>}>
        <NotFound />
      </Suspense>
    ),
  },
]);

export default router

Diferencias entre BrowserRouter y createBrowserRouter

En React Router v6.4, tanto BrowserRouter como createBrowserRouter son utilizados para manejar el enrutamiento en aplicaciones React, pero presentan diferencias significativas en su configuración y capacidades.

BrowserRouter es el componente tradicional que envuelve la aplicación y permite la navegación mediante el historial del navegador. Su configuración suele ser más sencilla y directa, pero menos flexible en comparación con createBrowserRouter.

// App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home/Home';
import About from './pages/About/About';

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}

Por otro lado, createBrowserRouter es un método introducido en React Router v6.4 que proporciona una configuración más flexible y directa. Permite definir rutas y su configuración en un solo lugar, ofreciendo capacidades avanzadas como loaders, actions y manejo de errores directamente en las rutas.

// router.jsx
import { createBrowserRouter } from 'react-router-dom';
import Home from './pages/Home/Home';
import Login, { loginAction } from './pages/Login/Login';
import ErrorPage from './pages/ErrorPage/ErrorPage';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    errorElement: <ErrorPage />,
    loader: async () => {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const todo = await response.json();
      return todo;
    },
  },
  {
    path: 'login',
    element: <Login />,
    errorElement: <ErrorPage />,
    action: loginAction,
  },
]);

export default router
// main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { RouterProvider } from 'react-router-dom';
import router from './router';

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <RouterProvider router={router} />
  </StrictMode>,
)

Las principales diferencias entre BrowserRouter y createBrowserRouter son los siguientes:

Configuración de rutas: BrowserRouter utiliza el componente Routes y Route para definir las rutas dentro de la estructura JSX, mientras que createBrowserRouter permite definir rutas directamente en una configuración de objetos.

Loaders y actions: createBrowserRouter proporciona soporte nativo para loaders y actions, permitiendo operaciones asíncronas y manejo de datos directamente en la definición de rutas. BrowserRouter no tiene esta funcionalidad integrada y requiere soluciones adicionales para manejar datos asíncronos.

Manejo de errores: createBrowserRouter permite definir componentes de error específicos para manejar errores en las rutas mediante la propiedad errorElement. Con BrowserRouter, el manejo de errores suele ser más manual y menos integrado.

Flexibilidad y mantenibilidad: createBrowserRouter ofrece una configuración más centralizada y declarativa, lo que puede mejorar la mantenibilidad y la claridad del código en aplicaciones grandes. BrowserRouter sigue siendo adecuado para aplicaciones más simples o donde se prefiera una configuración más directa.

Estos puntos destacan cómo createBrowserRouter proporciona una mayor flexibilidad y capacidades avanzadas en comparación con BrowserRouter, haciéndolo una opción preferida en proyectos que requieren una gestión más compleja del enrutamiento y los datos.

Aprende React online

Otras lecciones de React

Accede a todas las lecciones de React y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A React Y Su Ecosistema

React

Introducción Y Entorno

Instalar React Y Crear Nuevo Proyecto

React

Introducción Y Entorno

Introducción A Jsx

React

Componentes

Introducción A Componentes

React

Componentes

Componentes Funcionales

React

Componentes

Eventos En React

React

Componentes

Props Y Manejo De Datos Entre Componentes

React

Componentes

Renderizado Condicional

React

Componentes

Renderizado Iterativo Con Bucles

React

Componentes

Manejo De Clases Y Estilos

React

Componentes

Introducción A Los Hooks

React

Hooks

Estado Y Ciclo De Vida De Los Componentes

React

Hooks

Hooks Estado Y Efectos Secundarios

React

Hooks

Hooks Para Gestión De Estado Complejo Y Contexto

React

Hooks

Hooks Optimización Y Concurrencia

React

Hooks

Introducción A React Router

React

Navegación Y Enrutamiento

Definición Y Manejo De Rutas

React

Navegación Y Enrutamiento

Rutas Anidadas Y Rutas Dinámicas

React

Navegación Y Enrutamiento

Navegación Programática Redirección

React

Navegación Y Enrutamiento

Nuevos Métodos Create De React Router

React

Navegación Y Enrutamiento

Solicitudes Http Con Fetch Api

React

Interacción Http Con Backend

Solicitudes Http Con Axios

React

Interacción Http Con Backend

Estado Local Con Usestate Y Usereducer

React

Servicios Y Gestión De Estado

Estado Global Con Context Api

React

Servicios Y Gestión De Estado

Estado Global Con Redux Toolkit

React

Servicios Y Gestión De Estado

Custom Hooks Para Servicios Compartidos

React

Servicios Y Gestión De Estado

Evaluación Test React

React

Evaluación

Accede GRATIS a React y certifícate

Ejercicios de programación de React

Evalúa tus conocimientos de esta lección Nuevos métodos create de React Router con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender las diferencias entre BrowserRouter y createBrowserRouter.
  • Implementar rutas con createBrowserRouter.
  • Manejar errores de enrutamiento con createBrowserRouter.
  • Utilizar loader y action para operaciones asíncrona.
  • Definir rutas en JSX con createRoutesFromElements.
  • Integrar Suspense y lazy para carga diferida de componentes.