Compartir en Twitter
Go to Homepage

TUTORIAL COMPLETO DE REACT CON EJEMPLOS PRÁCTICOS 2025

December 3, 2025

Introducción a React y su Relevancia en 2025

React es una biblioteca de JavaScript ampliamente utilizada para construir interfaces de usuario interactivas y escalables. Su enfoque basado en componentes permite a los desarrolladores crear aplicaciones web modernas con un código limpio y reutilizable. En 2025, React sigue siendo una de las herramientas líderes en el desarrollo frontend, gracias a su ecosistema maduro, la incorporación de hooks para gestionar estado y su compatibilidad con tecnologías como Vite y Next.js. Este tutorial presenta ejemplos prácticos para dominar React, desde la creación de componentes hasta la gestión avanzada de estado y enrutamiento, adaptados al contexto tecnológico actual.

Para comenzar, asegúrate de tener Node.js (versión 18 o superior) instalado y un entorno de desarrollo configurado. Puedes iniciar un proyecto React utilizando herramientas modernas como Vite, que ofrece una configuración rápida y optimizada.

npm create vite@latest mi-proyecto -- --template react
cd mi-proyecto
npm install
npm run dev

Este comando genera un proyecto React con Vite, listo para desarrollar.

Creación de Componentes Funcionales

Los componentes funcionales son la base de React en 2025, reemplazando casi por completo a los componentes de clase debido a su simplicidad y la adopción de hooks. Un componente funcional es una función de JavaScript que retorna JSX, el cual describe la interfaz de usuario.

import React from "react";

function Saludo({ nombre }) {
    return <h1>Hola, {nombre}!</h1>;
}

export default Saludo;

En este ejemplo, el componente Saludo recibe una prop nombre y renderiza un encabezado personalizado. Para usarlo, importa el componente en otro archivo y pásale un valor:

import Saludo from "./Saludo";

function App() {
    return <Saludo nombre="Mundo" />;
}

export default App;

El resultado en el navegador será:

Hola, Mundo!

Las props en componentes permiten pasar datos dinámicos, haciendo los componentes reutilizables. Evita modificar las props directamente, ya que son inmutables.

Gestión de Estado con useState

El hook useState es fundamental para añadir estado a componentes funcionales. Permite almacenar y actualizar datos que afectan el renderizado del componente.

import React, { useState } from "react";

function Contador() {
    const [contador, setContador] = useState(0);

    return (
        <div>
            <p>Contador: {contador}</p>
            <button onClick={() => setContador(contador + 1)}>
                Incrementar
            </button>
        </div>
    );
}

export default Contador;

En este ejemplo, useState(0) inicializa el estado contador con un valor de 0. La función setContador actualiza el estado, desencadenando un nuevo renderizado. El botón incrementa el contador al hacer clic, mostrando el valor actualizado en la interfaz.

Es importante no mutar el estado directamente, sino usar la función proporcionada por useState para garantizar que React detecte los cambios.

Efectos Secundarios con useEffect

El hook useEffect maneja efectos secundarios, como llamadas a APIs, suscripciones o manipulaciones del DOM, que ocurren después de que el componente se renderiza.

import React, { useState, useEffect } from "react";

function ListaUsuarios() {
    const [usuarios, setUsuarios] = useState([]);

    useEffect(() => {
        fetch("https://jsonplaceholder.typicode.com/users")
            .then((response) => response.json())
            .then((data) => setUsuarios(data));
    }, []);

    return (
        <ul>
            {usuarios.map((usuario) => (
                <li key={usuario.id}>{usuario.name}</li>
            ))}
        </ul>
    );
}

export default ListaUsuarios;

Aquí, useEffect realiza una llamada a una API al montar el componente. El array de dependencias vacío ([]) asegura que el efecto solo se ejecute una vez, similar al método componentDidMount en componentes de clase. La lista de usuarios se renderiza dinámicamente usando map.

Si necesitas actualizar el efecto cuando cambian ciertas variables, incluye esas variables en el array de dependencias:

useEffect(() => {
    console.log("Contador cambió:", contador);
}, [contador]);

Esto registra un mensaje cada vez que contador cambia, demostrando cómo gestionar efectos secundarios en React.

Formularios y Entrada de Usuario

Los formularios en React se gestionan mediante estado controlado, donde los valores de los inputs están vinculados al estado del componente.

import React, { useState } from "react";

function Formulario() {
    const [nombre, setNombre] = useState("");

    const manejarEnvio = (e) => {
        e.preventDefault();
        alert(`Nombre enviado: ${nombre}`);
    };

    return (
        <form onSubmit={manejarEnvio}>
            <input
                type="text"
                value={nombre}
                onChange={(e) => setNombre(e.target.value)}
                placeholder="Ingresa tu nombre"
            />
            <button type="submit">Enviar</button>
        </form>
    );
}

export default Formulario;

En este ejemplo, el valor del input está controlado por el estado nombre. El evento onChange actualiza el estado con cada cambio en el input, y onSubmit maneja el envío del formulario, mostrando una alerta con el nombre ingresado.

Para manejar múltiples campos, puedes usar un objeto en el estado:

const [formData, setFormData] = useState({
    nombre: "",
    email: "",
});

const manejarCambio = (e) => {
    setFormData({
        ...formData,
        [e.target.name]: e.target.value,
    });
};

Esto permite escalar formularios complejos de manera eficiente.

Enrutamiento con React Router

React Router es una biblioteca esencial para crear aplicaciones de página única (SPA) con navegación dinámica. En 2025, React Router v6.4+ es la versión estándar, con mejoras en la gestión de rutas y carga de datos.

Primero, instala React Router:

npm install react-router-dom

Configura las rutas en tu aplicación:

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

function Inicio() {
    return <h2>Página de Inicio</h2>;
}

function Acerca() {
    return <h2>Acerca de Nosotros</h2>;
}

function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Inicio />} />
                <Route path="/acerca" element={<Acerca />} />
            </Routes>
        </BrowserRouter>
    );
}

export default App;

Este código define dos rutas: una para la página de inicio (/) y otra para la página “Acerca” (/acerca). El componente BrowserRouter envuelve la aplicación, mientras que Routes y Route definen las rutas.

Para agregar navegación, usa el componente Link:

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

function BarraNavegacion() {
    return (
        <nav>
            <Link to="/">Inicio</Link> | <Link to="/acerca">Acerca</Link>
        </nav>
    );
}

Incluye BarraNavegacion en App para permitir la navegación entre páginas sin recargar el navegador, mejorando la experiencia del usuario en aplicaciones de página única.

Renderizado Condicional

El renderizado condicional permite mostrar diferentes elementos en función del estado o las props. Esto es útil para interfaces dinámicas, como mostrar un mensaje de carga mientras se obtienen datos.

import React, { useState, useEffect } from "react";

function CargaDatos() {
    const [cargando, setCargando] = useState(true);
    const [datos, setDatos] = useState(null);

    useEffect(() => {
        setTimeout(() => {
            setDatos({ mensaje: "Datos cargados" });
            setCargando(false);
        }, 2000);
    }, []);

    if (cargando) {
        return <p>Cargando...</p>;
    }

    return <p>{datos.mensaje}</p>;
}

export default CargaDatos;

En este ejemplo, el componente muestra “Cargando…” durante dos segundos antes de renderizar los datos simulados. Puedes combinar operadores ternarios o lógicos para renderizado condicional más complejo:

return <div>{datos ? <p>{datos.mensaje}</p> : <p>Sin datos</p>}</div>;

Esto mejora la flexibilidad de las interfaces, adaptándolas al estado de la aplicación.

Listas y Claves

Renderizar listas en React implica usar el método map para iterar sobre un array y generar elementos JSX. Cada elemento debe tener una prop key única para ayudar a React a optimizar las actualizaciones.

import React from "react";

function ListaTareas() {
    const tareas = ["Aprender React", "Construir proyecto", "Optimizar código"];

    return (
        <ul>
            {tareas.map((tarea, indice) => (
                <li key={indice}>{tarea}</li>
            ))}
        </ul>
    );
}

export default ListaTareas;

Aquí, indice se usa como clave, pero es preferible usar un identificador único, como un ID de base de datos, para evitar problemas si la lista cambia:

const tareas = [
    { id: 1, texto: "Aprender React" },
    { id: 2, texto: "Construir proyecto" },
    { id: 3, texto: "Optimizar código" },
];

return (
    <ul>
        {tareas.map((tarea) => (
            <li key={tarea.id}>{tarea.texto}</li>
        ))}
    </ul>
);

Las claves en listas aseguran un renderizado eficiente, especialmente en listas dinámicas.

Componentes de Alto Orden

Los componentes de alto orden (HOC) son funciones que toman un componente y devuelven uno nuevo con funcionalidades adicionales. Son útiles para reutilizar lógica, como autenticación o manejo de datos.

import React from "react";

function conAutenticacion(Componente) {
    return function ComponenteProtegido(props) {
        const estaAutenticado = true; // Simulación de autenticación

        return estaAutenticado ? (
            <Componente {...props} />
        ) : (
            <p>Por favor, inicia sesión.</p>
        );
    };
}

function PerfilUsuario({ nombre }) {
    return <h2>Bienvenido, {nombre}</h2>;
}

const PerfilProtegido = conAutenticacion(PerfilUsuario);

function App() {
    return <PerfilProtegido nombre="Ana" />;
}

export default App;

En este ejemplo, conAutenticacion envuelve PerfilUsuario, mostrando el componente solo si estaAutenticado es true. Los HOC son una técnica avanzada para compartir lógica entre componentes.

Gestión de Estado Global con Context

El Context API de React permite compartir estado entre componentes sin pasar props manualmente. Es ideal para datos globales, como temas o autenticación.

import React, { createContext, useContext, useState } from "react";

const TemaContext = createContext();

function TemaProvider({ children }) {
    const [tema, setTema] = useState("claro");

    return (
        <TemaContext.Provider value={{ tema, setTema }}>
            {children}
        </TemaContext.Provider>
    );
}

function BotonTema() {
    const { tema, setTema } = useContext(TemaContext);

    return (
        <button onClick={() => setTema(tema === "claro" ? "oscuro" : "claro")}>
            Cambiar a tema {tema === "claro" ? "oscuro" : "claro"}
        </button>
    );
}

function App() {
    return (
        <TemaProvider>
            <BotonTema />
        </TemaProvider>
    );
}

export default App;

Aquí, TemaContext almacena el estado del tema, y BotonTema lo consume para cambiar entre temas claro y oscuro. El Context API simplifica la gestión de estado global en aplicaciones medianas.

Optimización con useMemo y useCallback

Los hooks useMemo y useCallback optimizan el rendimiento al memorizar valores y funciones, evitando cálculos o renderizados innecesarios.

import React, { useState, useMemo } from "react";

function ListaNumeros() {
    const [numeros, setNumeros] = useState([1, 2, 3, 4, 5]);

    const suma = useMemo(() => {
        console.log("Calculando suma...");
        return numeros.reduce((acc, num) => acc + num, 0);
    }, [numeros]);

    return (
        <div>
            <p>Suma: {suma}</p>
            <button
                onClick={() => setNumeros([...numeros, numeros.length + 1])}
            >
                Agregar número
            </button>
        </div>
    );
}

export default ListaNumeros;

En este ejemplo, useMemo calcula la suma de numeros solo cuando el array cambia, evitando cálculos redundantes. De manera similar, useCallback memoriza funciones para prevenir recreaciones innecesarias:

import React, { useState, useCallback } from "react";

function BotonContador() {
    const [contador, setContador] = useState(0);

    const incrementar = useCallback(() => {
        setContador((prev) => prev + 1);
    }, []);

    return <button onClick={incrementar}>Contador: {contador}</button>;
}

Esto asegura que incrementar no se recree en cada renderizado, mejorando el rendimiento en componentes hijos.

Estructura de Proyecto Recomendada

Una estructura de proyecto bien organizada facilita el mantenimiento y la escalabilidad. A continuación, se muestra una estructura común para un proyecto React en 2025:

mi-proyecto/
├── public/
│   ├── index.html
│   └── favicon.ico
├── src/
│   ├── assets/
│   │   └── images/
│   ├── components/
│   │   ├── Saludo.jsx
│   │   └── Contador.jsx
│   ├── pages/
│   │   ├── Inicio.jsx
│   │   └── Acerca.jsx
│   ├── context/
│   │   └── TemaContext.jsx
│   ├── App.jsx
│   ├── main.jsx
│   └── styles.css
├── package.json
└── vite.config.js
  • public/: Archivos estáticos.
  • src/assets/: Imágenes y otros recursos.
  • src/components/: Componentes reutilizables.
  • src/pages/: Componentes que representan páginas.
  • src/context/: Contextos para estado global.

Esta estructura soporta aplicaciones pequeñas y grandes, manteniendo el código organizado.

Conclusiones

React en 2025 es una herramienta poderosa y flexible para construir aplicaciones web modernas. Este tutorial cubrió los fundamentos, desde la creación de componentes funcionales hasta técnicas avanzadas como el Context API y la optimización con useMemo. Los ejemplos prácticos demuestran cómo implementar características comunes, como formularios, enrutamiento y gestión de estado, mientras se adoptan las mejores prácticas para un código limpio y eficiente. Al dominar estos conceptos, estarás preparado para desarrollar aplicaciones escalables y adaptarte a las demandas del desarrollo frontend actual. Continúa explorando el ecosistema de React, experimentando con herramientas como Vite, TanStack Query y Next.js para llevar tus proyectos al siguiente nivel.