Fundamentos de navegación en la web

1

Navegación Web con React Router: Fundamentos y Prácticas Avanzadas

2

Server-side Rendering vs Single Page Applications: Ventajas y Desventajas

3

Uso de React Router DOM 6 en Proyectos React

Introducción a React Router DOM 6

4

Instalación de React Router DOM 6 en un proyecto React

5

Uso de Hash Router en Aplicaciones Web con React Router DOM

6

Creación de Rutas Dinámicas con React Router DOM 6

7

Navegación en React Router: Uso de Link y NavLink

8

Rutas dinámicas con React Router DOM y useParams

9

Uso de useNavigate en React Router DOM para navegación dinámica

10

Uso de Outlet y Nested Routes en React Router DOM 6

Fake authentication con React Router DOM 6

11

Autenticación y Autorización en Apps con React Router y Hooks

12

Control de Acceso en Menú con Autenticación React

13

Protección de Rutas con React Router y Hooks

14

Roles y permisos en aplicaciones web: Autenticación y autorización

15

Retos avanzados en React: manejo de estado y composición de componentes

16

Mejorando la Redirección Post-Login en Aplicaciones Web

17

Roles y Permisos Avanzados en React Router v6

React Router en TODO Machine

18

Migración de Todo Machine a React Router 6

19

Organización de carpetas y rutas en React con React Router DOM 6

20

Maquetación de Botón Editar en Lista de Tareas con React

21

Generación de IDs únicos para gestionar tareas en React

22

Migración de modales a rutas en React: implementación práctica

23

Editar ToDos en React con Custom Hook y URL Parameters

24

Mejora de la Experiencia del Usuario al Editar To Do's en React

25

Implementación de React Router en Proyectos Legacy

Próximos pasos

26

Filtrado de Búsquedas en URL con React Router

27

Migración de React Router: de la versión 6 a la 5 en proyectos empresariales

28

Clonación de Platzi Movies usando React y React Router

29

Clonación de React Router en Componentes React

30

Navegación Avanzada con React Router DOM 6

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Creación de Rutas Dinámicas con React Router DOM 6

6/30
Recursos

¿Cómo crear rutas dinámicas con React Router DOM y React Router?

Aprender a crear rutas dinámicas en tu aplicación de React puede parecer un reto, pero con React Router DOM, el proceso se vuelve intuitivo y manejable. Comenzamos eliminando el código de ejemplo generado por Create React App y seguimos por importar los componentes esenciales de React Router DOM.

¿Cuáles componentes son necesarios para iniciar?

El punto de partida para trabajar con rutas en React es decidir qué tipo de enrutador se va a utilizar. Puedes elegir entre BrowserRouter, HashRouter y MemoryRouter. En nuestro caso, optamos por HashRouter porque facilita el despliegue en GitHub Pages. Además, necesitas importar Routes y Route para definir y gestionar las rutas.

¿Cómo implementamos las rutas en un componente?

Insertar rutas en tu aplicación requiere de un encuadre adecuado dentro del componente principal:

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

function App() {
  return (
    <HashRouter>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/blog" element={<BlogPage />} />
        <Route path="/profile" element={<ProfilePage />} />
        <Route path="*" element={<NotFoundPage />} />
      </Routes>
    </HashRouter>
  );
}

¿Cuál es la estructura necesaria para los componentes de página?

Para cada ruta, se debe crear un componente correspondiente. Aquí tienes un ejemplo sencillo para el componente HomePage:

import React from 'react';

export const HomePage = () => {
  return <h1>Home Page</h1>;
};

Repite el mismo patrón para los otros componentes, como BlogPage y ProfilePage, asegurándote de cambiar el nombre del componente y el contenido que retornarás adecuadamente.

¿Qué importancia tienen los componentes Routes y Route?

El componente Routes, anteriormente conocido como Switch, permite definir las rutas que harán que partes de la aplicación cambien dinámicamente. Dentro de Routes, los componentes Route se encargan de renderizar el componente adecuado basado en el path especificado.

¿Cómo manejar rutas no encontradas?

Es crucial para la experiencia de usuario gestionar rutas no encontradas. Se logra mediante la adición de un Route que coincide con path="*", asegurando así que cualquier URL indefinida muestre un componente de NotFoundPage.

¿Qué papel juega un componente común como el menú?

Tener un componente como Menu que permanezca visible en todas las rutas es esencial para la navegación. Este componente debería estar dentro del HashRouter, pero fuera de los componentes Routes, permitiendo acceso a la información de navegación:

import React from 'react';

export const Menu = () => {
  return (
    <nav className="navbar">
      <h1>Menu</h1>
      {/* Aquí irían los enlaces de navegación */}
    </nav>
  );
};

¿Cómo aseguramos que todos los componentes tengan acceso a la navegación?

Colocar el menú dentro del HashRouter garantiza que, al igual que los componentes de ruta, tenga acceso a la información del proveedor de navegación para gestionar rutas más avanzadas y autenticaciones.

¡Listo! No olvides que a medida que construyes tus aplicaciones, experimentarás con opciones como el Link y NavLink de React Router. Estos componentes serán fundamentales en próximas lecciones para mejorar tu aplicación y hacer la navegación más intuitiva y dinámica. Continúa adelante y explora las inmensas posibilidades que React Router DOM te ofrece para tus proyectos.

Aportes 14

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

No importa si dejamos el path=’*’ al principio ya que react-router implementa un algoritmo que determina la importancia de la ruta, asi que siempre va a dar prioridad a ruta definidas y si despues de eso no encuentra ninguna ahora si renderizaria el *

Un comando interesante para cuando estamos creando nuestros componentes es **rfcp ** o **rafc **(abreviatura de React Functional Component)

Route: componentes de navegación

Vamos a crear nuestras primeras rutas con React 😀.

En nuestro archivo App vamos a importar un par de componentes que nos da React Router DOM:

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

Luego en nuestro componente App vamos a escribir un código de ejemplo para entender como funcionan estos componentes.

function App() {
  return (
    <>
    {/* Este es un provider */}
      <HashRouter>
        <Menu />

        {/* Esta es la parte de la aplicación que va cambiar de 
        manera dinámica según las rutas */}
        <Routes>

          {/* Este componente recibe las propiedades de 'path', que 
          es la ruta deseada y 'element', que es componente que 
          deseamos renderizar */}
          <Route path='/' element={<HomePage />} />
          <Route path='/blog' element={<BlogPage />} />
          <Route path='/profile' element={<ProfilePage />} />

        </Routes>

      </HashRouter>
    </>
  )
}

Podemos agregar una ruta al final que sea para todas las rutas que no hayamos definido, esto lo hacemos añadiendo un ‘*’ en la propiedad path de nuestra ruta, si lo hacemos al final de todas las rutas en caso de que no estén definidas retornará algo que nosotros definamos, con esto por ejemplo podemos crear una página de no encontrado.

<Route path='*' element={<p>Not Found</p>} />

Ahora debemos crear estos componentes que añadimos en los path ya que estos no existen.

HomePage.js

import React from 'react';

function HomePage() {
  return (
    <h1>Home Page</h1>
  );
}

export { HomePage }

BlogPage.js

import React from 'react';

function BlogPage() {
  return (
    <h1>Blog Page</h1>
  );
}

export { BlogPage }

ProfilePage.js

import React from 'react';

function ProfilePage() {
  return (
    <h1>Profile Page</h1>
  );
}

export { ProfilePage }

Menu.js

import React from 'react';

function Menu() {
  return (
    <nav>Menú</nav>
  );
}

export { Menu }

Y los importamos a nuestro archivo App:

import { Menu } from './Components/Menu/Menu';
import { HomePage } from './Components/Routes/HomePage/HomePage';
import { BlogPage } from './Components/Routes/BlogPage/BlogPage';
import { ProfilePage } from './Components/Routes/ProfilePage/ProfilePage';

Si jugamos con la ruta usando los hast navigaror /#/ veremos que efectivamente si funcionan y cargan nuestros componentes.

El atajo de VS Code por default es alt + space
recuerden que deben tener abiertos los componentes para que les de el path.

estoy usando reacto router 6.8 y cambio muchisimo, para usarlo ahora es asi:

import Menu from './Menu';

import './index.css';

//* /#/
//* /#/blog
//* /#/profile
//* /#/lalala -> not found

const router = createHashRouter([
  {
    path: '/',
    element: <HomePage />,
  },
  {
    path: '/blog',
    element: <BlogPage />,
  },
  {
    path: '/profile',
    element: <ProfilePage />,
  },
  {
    path: '*',
    element: <p>Not Found</p>,
  },
]);

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <Menu />
    <RouterProvider router={router} />
  </React.StrictMode>
);

ahora se usa create hash router y un routerProvider, para mas info en la documentacion:

En los proyectos en los que he trabajado siempre hemos usado el router de tipo Browser Router y los Hash Router son nuevos para mi por lo que estoy emocionada por aprenderlos!

El código de App.js, por si lo necesitan:

import { HashRouter, Route, Routes } from 'react-router-dom'
import { BlogPage } from './BlogPage';
import { HomePage } from './HomePage';
import { Menu } from './Menu';
import { ProfilePage } from './ProfilePage';
import React from 'react'

function App() {
  return (
    <>
      <HashRouter>
        <Menu/>
        <Routes>//Esta parte va a ser dinamica, osea que va a cambiar dependiendo de la ruta en la que estemos
          <Route path='/' element={<HomePage/>}/>
          <Route path='/blog' element={<BlogPage/>}/>
          <Route path='/profile' element={<ProfilePage/>}/>
          <Route path='/*' element={<p>Not found</p>}/>//Cuando ponemos un asterisco (*) nos referimos a que sea el valor por defecto si las rutas de arriba no se cumple.

        </Routes>
      </HashRouter>
    </>
  );
}

export default App;

Me coloque a experimentar que pasaba si cambiaba el hash con un onClick en el componente <Menu/> y a si fue el resultado.

import React from "react";

export function Menu (){
    return (
        <nav>
            <ul>
                <li onClick={()=>location.hash='#/'}>Home</li>
                <li onClick={()=> location.hash='#/profile'}>Profile</li>
                <li onClick={()=> location.hash= '#/blog'}>BLog Page</li>
            </ul>
        </nav>
    )
}

Asi dinamicamente cambiamos la direccion o el hash de la pagina y el react router atomaticamente nos renderiza los componentes que esten ligados a ese hash

Excelente clase!!👏👏, por fin aclare las dudas del Curso Practico de React.
.
😅😅Me atrevo a decir que tome primero el Practico de React. Por que este curso no estaba disponible.

Route: componentes de navegación

.
Vamos a empezar a crear nuestras primeras rutas con React Router DOM 6 y vamos a utilizar HashRouter.
.
En nuestro archivo App.js vamos a importar algunos componentes desde react-router-dom:
.

  • HashRouter: Primero vamos a necesitar un router, pudo haber sido un BrowserRouter o un MemoryRouter, sin embargo utilizaremos un HashRouter debido a que planeamos desplegarlo en GitHub Pages. Este componente funge de provider.
    .
  • Routes: Contienen a las rutas dinámicas
    .
  • Route: Es la ruta en sí e indica qué componente renderizar.

.

import { HashRouter, Routes, Route } from 'react-router-dom';
import { Menu } from './Menu';
import { HomePage } from './HomePage';
import { BlogPage } from './BlogPage';
import { ProfilePage } from './ProfilePage';

function App() {
  return (
    <>
      <HashRouter>
        <Menu />

        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/blog" element={<BlogPage />} />
          <Route path="/profile" element={<ProfilePage />} />
          <Route path="*" element={<p>Not found</p>} />
        </Routes>
      </HashRouter>
    </>
  );
}

export default App;

.
Lo primero que podemos observar es que nuestro componente HashRouter va a contener a los demás componentes, esto porque es un provider. Lo que pongamos adentro que esté por de fuera de Routes se va a renderizar en todas las páginas, como en este caso el componente Menu.
.
Como dijimos, vamos a también tener nuestras rutas dinámicas dentro de un componente Routes, que sin embargo dependiendo de la versión que estemos utilizando podría cambiar de nombre a Switch por ejemplo.
.
Dentro de Routes tendremos a las rutas Route en sí, cada una de ellas define una ruta que tiene como propiedades al path y al element. Normalmente este componente no se abre y se cierra, solo se cierra.
.
En nuestro componente Route la propiedad path define la ruta que va después de /#/. La propiedad element que dependiendo de la versión y el tipo de React Router que estemos utilizando, puede cambiar de nombre a render o component, sin embargo independientemente del nombre que tenga lo que hace es indicar qué componente se va a renderizar cuando accedamos a la ruta definida en la propiedad path.
.
Las rutas definidas en Routes son algo independientes del tipo de router; es decir, que no saben si estamos utilizando un hash router o un browser router. Por lo que si decidimos cambiar el tipo de router no tendremos que modificar las rutas porque por si solas se acoplaran después de un /#/ si estuviéramos utilizando un HashRouter o directamente después del / si estamos utilizando un BrowserRouter. Debido a ello en la propiedad path del componente Router ponemos las rutas de forma normal, luego nuestro provider se encargará de ponerle los hashes si este lo requiere.
.
Como podemos contemplar hemos creado varias rutas que renderizarán un componente en específico dependiendo de la ruta en la que estamos. Sin embargo, una de esas rutas es simplemente un * que significa cualquier ruta que no hayamos definido anteriormente, a lo cual vamos a responder renderizando un Not Found. Esta ruta genérica es recomendable posicionarla al final para evitar posibles conflictos; dependiendo de la versión que utilicemos, el colocarlo como primera ruta podría significar que las consecuentes no se lean, dando Not Found para todas las rutas.
.
En cuanto al componente Menu es importante que esté por dentro del componente HashRouter debido a que de esta forma va a poder consumir la información del provider.
.
Finalmente, se deben de realizar las importaciones correspondientes y la creación de los componentes que se renderizan en las distintas rutas.
.
Como estamos utilizando lo que es HashRouter si yo en la url no pongo la ruta después de /#/, entonces no va a funcionar; incluso si pongo cualquier cosa donde se supone que me responda con Not Found, me seguirá dando la página principal.
.

/#/ -> HomePage
/#/blog -> BlogPage
/#/profile -> ProfilePage
/#/lalalala -> Not Found
/blog, /lalala -> HomePage
el comando rafce, con la extensión code snipets en vsc crea el componente automáticamente

Gracias a esta clase pude mejorar un poco un proyecto personal que había hecho anteriormente, que pasa el proyecto es una tienda de tenis(calzados) entonces quería que todo el nav bar y el footer se expadiera por toda la aplicación y poder buscar los articulos. Antes de este cambio tenia el footer y el header harcodeado en cada una de las pantallas y solo en la pantalla de home podia hacer las busqueda de los productos. Pero con el cambio todo mejoró aquí le dejo un antes y un después. Las partes subrayadas en rojo fueron agregadas con el nuevo cambio!

ANTES

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

import "./App.css";

import { useUserContext } from "./context/userContext";

import { auth } from "./firebase/credenciales";
import { onAuthStateChanged } from "firebase/auth";

import {
  Home,
  Product,
  Profile,
  Cart,
  Checkout,
  Login,
  NotFound,
} from "./views";

function App() {
  const { user, setUser } = useUserContext();
  onAuthStateChanged(auth, (firebaseUser) => {
    firebaseUser ? setUser(firebaseUser) : setUser(null);
  });
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="product/:id" element={<Product />} />
      <Route path="profile" element={<Profile />} />
      <Route path="cart" element={<Cart />} />
      <Route path="checkout" element={<Checkout />} />
      <Route path="login" element={<Login />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
}

export default App;

DESPUES


ARCHIVO HOME.JSX

ANTES

import React, { useState, useEffect } from "react";
import styled from "styled-components";

import Header from "../components/header";
import ItemCard from "../components/ItemCard";

import getActiveProducts from "../functions/getActiveProducts";

import Hero from "../assets/images/inicio.jpg";


const Home = () => {
  const [products, setProducts] = useState(null);
  const [searchValue, setSearchValue] = useState("");
  let searchedItems = [];

  useEffect(() => {
    async function getProducts() {
      const products = await getActiveProducts();
      setProducts(products);
    }
    getProducts();
  }, []);

  if (!searchValue.length >= 1) {
    searchedItems = products;
  } else {
    searchedItems = products.filter((product) => {
      const productName = product.name.toLowerCase();
      const searchText = searchValue.toLowerCase();
      return productName.includes(searchText);
    });
  }

  return (
    <Container>
      <HeroContainer>
        <Header setSearchValue={setSearchValue} searchValue={searchValue} />
        <HeroImage src={Hero} alt="hero" />
      </HeroContainer>
      <ListContainer>
        {searchedItems
          ? searchedItems.map((itemProduct) => (
              <li key={itemProduct.id}>
                <ItemCard product={itemProduct} />
              </li>
            ))
          : null}
      </ListContainer>
    </Container>
  );
};

export default Home;

const Container = styled.div`
  display: flex;
  flex-direction: column;
  @media (min-width: 768px) {
    gap: 10px;
    align-items: center;
    justify-content: space-around;
  }
`;

const ListContainer = styled.ul`
  padding: 0;
  list-style: none;
  justify-content: center;
  @media (min-width: 768px) {
    gap: 10px;
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }
  @media (min-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
  }
  @media (min-width: 1440px) {
    grid-template-columns: repeat(4, 1fr);
  }
`;

const HeroContainer = styled.picture`
  width: 100%;
`;

const HeroImage = styled.img`
  width: 100%;
  height: auto;
  min-width: 288px;
  background-size: cover;
`;
import React from 'react';
import { HashRouter, Routes, Route } from 'react-router-dom'
import { HomePage } from './pages/HomePage';
import { BlogPage } from './pages/BlogPage';
import { ProfilePage } from './pages/ProfilePage';
import { Menu } from './components/Menu';

function App() {
  return (
    <>
      <HashRouter>
        <Menu />
        <Routes>
          <Route path='/' element={<HomePage />} />
          <Route path='/blog' element={<BlogPage />} />
          <Route path='/profile' element={<ProfilePage />} />
          <Route path='*' element={<p>Not found</p>} />
        </Routes>
      </HashRouter>
    </>
  );
}

export default App;

Asi es como se hace el router 19 sep 2023

import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider, createBrowserRouter } from 'react-router-dom'
import BlogPage from './pages/BlogPage.jsx'
import HomePage from './pages/HomePage.jsx'
import ProfilePage from './pages/ProfilePage'
import Menu from './Menu'

const router = createBrowserRouter([
  {
    path: "/",
    element: <HomePage/>
  },
  {
    path: "/blog",
    element: <BlogPage/>
  },
  {
    path: "/profile",
    element: <ProfilePage/>
  },
  {
    path: "*",
    element: <p>Not found</p>
  },
])


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

Todo esto lo hice desde el archivo main, ya no fue necesario hacerlo en el archivo app