Curso react nivel medio

Conceptos Básicos**

1. Configuración Básica

Objetivo: Aprender a configurar React Router DOM en un proyecto desde cero y crear tus primeras rutas.


Pasos:
  1. Instalación de React Router DOM Asegúrate de tener un proyecto de React configurado. Si no, puedes crear uno con:

    1npx create-react-app mi-app
    2cd mi-app

    Luego instala React Router DOM:

    1npm install react-router-dom
  2. Configurar el Router En el archivo principal (index.js o main.jsx), envuelve tu aplicación en un <BrowserRouter>:

    1import React from 'react';
    2import ReactDOM from 'react-dom';
    3import { BrowserRouter } from 'react-router-dom';
    4import App from './App';
    5
    6ReactDOM.render(
    7  <BrowserRouter>
    8    <App />
    9  </BrowserRouter>,
    10  document.getElementById('root')
    11);
  3. Crear Rutas Básicas En el componente App.js o App.jsx, utiliza <Routes> y <Route> para definir las páginas:

    1import React from 'react';
    2import { Routes, Route } from 'react-router-dom';
    3
    4const Home = () => <h1>Inicio</h1>;
    5const About = () => <h1>Acerca de</h1>;
    6
    7const App = () => {
    8  return (
    9    <div>
    10      <h1>Mi Aplicación</h1>
    11      <Routes>
    12        <Route path="/" element={<Home />} />
    13        <Route path="/about" element={<About />} />
    14      </Routes>
    15    </div>
    16  );
    17};
    18
    19export default App;
  4. Probar la Aplicación

    • Abre tu navegador y accede a http://localhost:3000/ para ver la página de inicio.
    • Ve a http://localhost:3000/about para ver la página "Acerca de".

2. Navegación entre Páginas

Objetivo: Aprender a usar <Link> y <NavLink> para navegar entre páginas sin recargar.


<Link> reemplaza las etiquetas <a> tradicionales para evitar recargas completas de la página.

  1. Agrega un menú de navegación:

    1import React from 'react';
    2import { Link, Routes, Route } from 'react-router-dom';
    3
    4const Home = () => <h1>Inicio</h1>;
    5const About = () => <h1>Acerca de</h1>;
    6
    7const App = () => {
    8  return (
    9    <div>
    10      <nav>
    11        <Link to="/">Inicio</Link> | <Link to="/about">Acerca de</Link>
    12      </nav>
    13      <Routes>
    14        <Route path="/" element={<Home />} />
    15        <Route path="/about" element={<About />} />
    16      </Routes>
    17    </div>
    18  );
    19};
    20
    21export default App;
  2. Prueba la navegación:

    • Haz clic en los enlaces y observa cómo cambia la URL sin recargar la página.

<NavLink> funciona igual que <Link> pero añade automáticamente una clase al enlace activo, útil para resaltar el enlace actual.

  1. Cambia <Link> por <NavLink>:

    1import React from 'react';
    2import { NavLink, Routes, Route } from 'react-router-dom';
    3
    4const Home = () => <h1>Inicio</h1>;
    5const About = () => <h1>Acerca de</h1>;
    6
    7const App = () => {
    8  return (
    9    <div>
    10      <nav>
    11        <NavLink to="/" style={({ isActive }) => ({ fontWeight: isActive ? 'bold' : 'normal' })}>
    12          Inicio
    13        </NavLink>{' '}
    14        |{' '}
    15        <NavLink
    16          to="/about"
    17          style={({ isActive }) => ({ fontWeight: isActive ? 'bold' : 'normal' })}
    18        >
    19          Acerca de
    20        </NavLink>
    21      </nav>
    22      <Routes>
    23        <Route path="/" element={<Home />} />
    24        <Route path="/about" element={<About />} />
    25      </Routes>
    26    </div>
    27  );
    28};
    29
    30export default App;
  2. Observa el enlace activo:

    • El enlace de la página actual aparecerá en negrita.

Hooks Principales**

En este módulo aprenderás a usar los hooks más interesantes de React Router DOM: useNavigate, useParams, useLocation y useSearchParams. Estos hooks te permitirán manejar navegación y datos relacionados con las rutas de manera programática.


1. useNavigate

Objetivo: Navegar programáticamente entre rutas.


Ejemplo 1: Redirección después de un evento
  1. Modifica tu archivo App.js para incluir una página de login:

    1import React from 'react';
    2import { Routes, Route, useNavigate } from 'react-router-dom';
    3
    4const Home = () => <h1>Inicio</h1>;
    5const Dashboard = () => <h1>Bienvenido al Dashboard</h1>;
    6
    7const Login = () => {
    8  const navigate = useNavigate();
    9
    10  const handleLogin = () => {
    11    // Simular un inicio de sesión exitoso
    12    navigate('/dashboard');
    13  };
    14
    15  return (
    16    <div>
    17      <h1>Iniciar Sesión</h1>
    18      <button onClick={handleLogin}>Iniciar</button>
    19    </div>
    20  );
    21};
    22
    23const App = () => {
    24  return (
    25    <div>
    26      <Routes>
    27        <Route path="/" element={<Home />} />
    28        <Route path="/login" element={<Login />} />
    29        <Route path="/dashboard" element={<Dashboard />} />
    30      </Routes>
    31    </div>
    32  );
    33};
    34
    35export default App;
  2. Prueba la redirección:

    • Ve a http://localhost:3000/login, haz clic en el botón "Iniciar", y serás redirigido al Dashboard.

2. useParams

Objetivo: Acceder a parámetros dinámicos de la URL.


Ejemplo 2: Detalles de un artículo basado en ID
  1. Modifica las rutas para incluir una página de detalles:

    1import React from 'react';
    2import { Routes, Route, useParams } from 'react-router-dom';
    3
    4const Home = () => (
    5  <div>
    6    <h1>Inicio</h1>
    7    <p>
    8      <a href="/article/1">Artículo 1</a>
    9    </p>
    10    <p>
    11      <a href="/article/2">Artículo 2</a>
    12    </p>
    13  </div>
    14);
    15
    16const ArticleDetail = () => {
    17  const { id } = useParams();
    18  return <h1>Detalles del Artículo {id}</h1>;
    19};
    20
    21const App = () => {
    22  return (
    23    <div>
    24      <Routes>
    25        <Route path="/" element={<Home />} />
    26        <Route path="/article/:id" element={<ArticleDetail />} />
    27      </Routes>
    28    </div>
    29  );
    30};
    31
    32export default App;
  2. Prueba los parámetros dinámicos:

    • Ve a http://localhost:3000/article/1 para ver "Detalles del Artículo 1".
    • Cambia el ID en la URL y observa cómo cambia el contenido.

3. useLocation

Objetivo: Obtener información sobre la ubicación actual.


Ejemplo 3: Mostrar un mensaje según la ubicación
  1. Modifica tu archivo para mostrar la ruta actual:

    1import React from 'react';
    2import { Routes, Route, useLocation } from 'react-router-dom';
    3
    4const Home = () => <h1>Inicio</h1>;
    5const About = () => <h1>Acerca de</h1>;
    6
    7const LocationDisplay = () => {
    8  const location = useLocation();
    9  return <p>Estás en: {location.pathname}</p>;
    10};
    11
    12const App = () => {
    13  return (
    14    <div>
    15      <LocationDisplay />
    16      <Routes>
    17        <Route path="/" element={<Home />} />
    18        <Route path="/about" element={<About />} />
    19      </Routes>
    20    </div>
    21  );
    22};
    23
    24export default App;
  2. Prueba la ubicación:

    • Cambia entre rutas y observa cómo se actualiza la información mostrada.

4. useSearchParams

Objetivo: Manejar parámetros de consulta (query strings) en la URL.


Ejemplo 4: Filtrar elementos
  1. Agrega una lista de productos con filtros:

    1import React from 'react';
    2import { Routes, Route, useSearchParams } from 'react-router-dom';
    3
    4const Home = () => {
    5  const [searchParams, setSearchParams] = useSearchParams();
    6  const filter = searchParams.get('filter') || '';
    7
    8  const handleFilterChange = (e) => {
    9    setSearchParams({ filter: e.target.value });
    10  };
    11
    12  const products = ['Manzana', 'Naranja', 'Plátano', 'Pera'];
    13  const filteredProducts = products.filter((product) =>
    14    product.toLowerCase().includes(filter.toLowerCase())
    15  );
    16
    17  return (
    18    <div>
    19      <h1>Productos</h1>
    20      <input
    21        type="text"
    22        value={filter}
    23        onChange={handleFilterChange}
    24        placeholder="Filtrar productos"
    25      />
    26      <ul>
    27        {filteredProducts.map((product, index) => (
    28          <li key={index}>{product}</li>
    29        ))}
    30      </ul>
    31    </div>
    32  );
    33};
    34
    35const App = () => {
    36  return (
    37    <div>
    38      <Routes>
    39        <Route path="/" element={<Home />} />
    40      </Routes>
    41    </div>
    42  );
    43};
    44
    45export default App;
  2. Prueba los filtros:

    • Ingresa texto en el campo de búsqueda y observa cómo se filtran los productos.

Rutas Avanzadas**

En este módulo exploraremos características más avanzadas de React Router DOM: rutas anidadas, rutas protegidas y manejo de errores.


1. Rutas Anidadas

Objetivo: Crear estructuras de rutas que representen relaciones jerárquicas entre páginas.


Ejemplo 1: Página con subsecciones
  1. Modifica las rutas para incluir páginas anidadas:

    1import React from 'react';
    2import { Routes, Route, Link, Outlet } from 'react-router-dom';
    3
    4const Dashboard = () => (
    5  <div>
    6    <h1>Dashboard</h1>
    7    <nav>
    8      <Link to="profile">Perfil</Link> | <Link to="settings">Configuración</Link>
    9    </nav>
    10    <Outlet />
    11  </div>
    12);
    13
    14const Profile = () => <h2>Perfil del Usuario</h2>;
    15const Settings = () => <h2>Configuración de la Cuenta</h2>;
    16
    17const App = () => {
    18  return (
    19    <div>
    20      <Routes>
    21        <Route path="/" element={<h1>Inicio</h1>} />
    22        <Route path="dashboard" element={<Dashboard />}>
    23          <Route path="profile" element={<Profile />} />
    24          <Route path="settings" element={<Settings />} />
    25        </Route>
    26      </Routes>
    27    </div>
    28  );
    29};
    30
    31export default App;
  2. Prueba las rutas:

    • Ve a http://localhost:3000/dashboard para ver el Dashboard.
    • Haz clic en "Perfil" o "Configuración" para navegar dentro del Dashboard.

2. Rutas Protegidas

Objetivo: Restringir el acceso a ciertas rutas basándote en una condición (por ejemplo, si el usuario está autenticado).


Ejemplo 2: Rutas protegidas con autenticación simulada
  1. Crea un componente para proteger rutas:

    1import React from 'react';
    2import { Navigate, Outlet } from 'react-router-dom';
    3
    4const useAuth = () => {
    5  const user = { loggedIn: true }; // Cambia a false para probar
    6  return user && user.loggedIn;
    7};
    8
    9const ProtectedRoute = () => {
    10  const isAuth = useAuth();
    11  return isAuth ? <Outlet /> : <Navigate to="/" />;
    12};
  2. Modifica las rutas para incluir protección:

    1const Dashboard = () => <h1>Dashboard</h1>;
    2
    3const App = () => {
    4  return (
    5    <div>
    6      <Routes>
    7        <Route path="/" element={<h1>Inicio</h1>} />
    8        <Route element={<ProtectedRoute />}>
    9          <Route path="dashboard" element={<Dashboard />} />
    10        </Route>
    11      </Routes>
    12    </div>
    13  );
    14};
    15
    16export default App;
  3. Prueba las rutas protegidas:

    • Ve a http://localhost:3000/dashboard. Si loggedIn es false, serás redirigido al inicio.

3. Manejo de Errores

Objetivo: Mostrar una página personalizada cuando una ruta no existe.


Ejemplo 3: Página 404
  1. Agrega una ruta "catch-all":

    1const NotFound = () => <h1>Página no encontrada (404)</h1>;
    2
    3const App = () => {
    4  return (
    5    <div>
    6      <Routes>
    7        <Route path="/" element={<h1>Inicio</h1>} />
    8        <Route path="*" element={<NotFound />} />
    9      </Routes>
    10    </div>
    11  );
    12};
    13
    14export default App;
  2. Prueba el manejo de errores:

    • Ve a una URL inexistente como http://localhost:3000/xyz para ver la página 404.

Optimización y Buenas Prácticas**

En este módulo, aprenderás técnicas para optimizar tus rutas con React Router DOM, incluyendo carga diferida (lazy loading), rutas con parámetros opcionales y manejo de errores más avanzado.


1. Carga Diferida (Lazy Loading)

Objetivo: Cargar componentes de forma diferida para mejorar el rendimiento de la aplicación.


Ejemplo 1: Lazy Loading con React Router DOM
  1. Utiliza React.lazy y Suspense para cargar componentes bajo demanda:

    1import React, { Suspense, lazy } from 'react';
    2import { Routes, Route } from 'react-router-dom';
    3
    4const Home = lazy(() => import('./Home')); // Componente cargado de forma diferida
    5const About = lazy(() => import('./About'));
    6
    7const App = () => {
    8  return (
    9    <div>
    10      <Suspense fallback={<h1>Cargando...</h1>}>
    11        <Routes>
    12          <Route path="/" element={<Home />} />
    13          <Route path="/about" element={<About />} />
    14        </Routes>
    15      </Suspense>
    16    </div>
    17  );
    18};
    19
    20export default App;
  2. Crea los componentes Home.jsx y About.jsx:

    1// Home.jsx
    2const Home = () => <h1>Inicio</h1>;
    3export default Home;
    4
    5// About.jsx
    6const About = () => <h1>Acerca de</h1>;
    7export default About;
  3. Prueba la carga diferida:

    • Observa cómo se muestra el mensaje de "Cargando..." mientras los componentes se cargan.

2. Rutas con Parámetros Opcionales

Objetivo: Manejar rutas que acepten parámetros opcionales.


Ejemplo 2: Parámetros opcionales
  1. Define una ruta con un parámetro opcional:

    1import React from 'react';
    2import { Routes, Route, useParams } from 'react-router-dom';
    3
    4const Greeting = () => {
    5  const { name } = useParams();
    6  return <h1>Hola, {name ? name : 'Visitante'}!</h1>;
    7};
    8
    9const App = () => {
    10  return (
    11    <div>
    12      <Routes>
    13        <Route path="/" element={<h1>Inicio</h1>} />
    14        <Route path="/greeting/:name?" element={<Greeting />} />
    15      </Routes>
    16    </div>
    17  );
    18};
    19
    20export default App;
  2. Prueba los parámetros opcionales:

    • Ve a http://localhost:3000/greeting para ver "Hola, Visitante!".
    • Ve a http://localhost:3000/greeting/Juan para ver "Hola, Juan!".

3. Manejo de Errores Mejorado

Objetivo: Implementar un sistema avanzado para manejar errores.


Ejemplo 3: Manejo de errores con un componente de "Error Boundary"
  1. Crea un componente para capturar errores:

    1import React from 'react';
    2
    3class ErrorBoundary extends React.Component {
    4  constructor(props) {
    5    super(props);
    6    this.state = { hasError: false };
    7  }
    8
    9  static getDerivedStateFromError() {
    10    return { hasError: true };
    11  }
    12
    13  componentDidCatch(error, errorInfo) {
    14    console.error('Error capturado:', error, errorInfo);
    15  }
    16
    17  render() {
    18    if (this.state.hasError) {
    19      return <h1>Algo salió mal. Por favor, intenta nuevamente.</h1>;
    20    }
    21
    22    return this.props.children;
    23  }
    24}
    25
    26export default ErrorBoundary;
  2. Usa el ErrorBoundary en tu aplicación:

    1import React, { lazy, Suspense } from 'react';
    2import { Routes, Route } from 'react-router-dom';
    3import ErrorBoundary from './ErrorBoundary';
    4
    5const Home = lazy(() => import('./Home'));
    6const About = lazy(() => import('./About'));
    7
    8const App = () => {
    9  return (
    10    <ErrorBoundary>
    11      <Suspense fallback={<h1>Cargando...</h1>}>
    12        <Routes>
    13          <Route path="/" element={<Home />} />
    14          <Route path="/about" element={<About />} />
    15        </Routes>
    16      </Suspense>
    17    </ErrorBoundary>
    18  );
    19};
    20
    21export default App;
  3. Prueba el manejo de errores:

    • Introduce un error en el componente About para ver cómo el ErrorBoundary lo captura.