Desarrollo de aplicaciones modernas con React
Guía completa para crear aplicaciones web eficientes y mantenibles con React.
InSkillCoach
Desarrollo de aplicaciones modernas con React
React es una de las bibliotecas de JavaScript más populares para la creación de interfaces de usuario. Desarrollada y mantenida por Facebook (Meta), permite construir aplicaciones web complejas con componentes reutilizables y una gestión eficaz del estado.
¿Por qué elegir React?
- Enfoque declarativo: Usted describe cómo debería verse su interfaz y React se encarga de las actualizaciones
- Basado en componentes: Cree elementos de interfaz encapsulados y reutilizables
- Ecosistema rico: Una amplia variedad de bibliotecas y herramientas complementarias
- Gran comunidad: Soporte, recursos y actualizaciones periódicas
- Rendimiento optimizado: Virtual DOM y reconciliación para actualizaciones eficientes
- Adoptado por grandes empresas: Facebook, Instagram, Netflix, Airbnb, etc.
Puesta en marcha de un proyecto React
Creación con Create React App
Create React App es una herramienta oficial que permite iniciar rápidamente un proyecto React:
# Instalación
npx create-react-app mon-application
# Inicio
cd mon-application
npm start
Uso de Vite (alternativa moderna)
Vite ofrece tiempos de compilación más rápidos y una mejor experiencia de desarrollo:
# Instalación
npm create vite@latest mon-application -- --template react
# Inicio
cd mon-application
npm install
npm run dev
Los fundamentos de React
Componentes
Los componentes son los bloques básicos de una aplicación React:
// Componente funcional
function Salutation(props) {
return <h1>Bonjour, {props.nom} !</h1>;
}
// Uso
<Salutation nom="Alice" />
JSX
JSX es una extensión de sintaxis que permite escribir HTML dentro de JavaScript:
const element = <h1>Bonjour, monde !</h1>;
// Con expresiones JavaScript
const nom = "Alice";
const element = <h1>Bonjour, {nom} !</h1>;
// Con atributos
const element = <img src={user.avatarUrl} alt="Avatar" />;
// Elementos anidados
const element = (
<div>
<h1>Titre</h1>
<p>Paragraphe</p>
</div>
);
Props
Las props permiten pasar datos de un componente padre a un componente hijo:
// Definición del componente
function Carte(props) {
return (
<div className="carte">
<h2>{props.titre}</h2>
<p>{props.description}</p>
{props.children}
</div>
);
}
// Uso
<Carte
titre="Mon titre"
description="Ma description"
>
<button>En savoir plus</button>
</Carte>
Estado (State)
El estado permite almacenar datos que pueden cambiar con el tiempo:
import { useState } from 'react';
function Compteur() {
// Declaración de un estado
const [compteur, setCompteur] = useState(0);
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
Ciclo de vida con Hooks
Los Hooks permiten usar el estado y otras funcionalidades de React en los componentes funcionales:
import { useState, useEffect } from 'react';
function ExempleEffet() {
const [compteur, setCompteur] = useState(0);
// Similar a componentDidMount y componentDidUpdate
useEffect(() => {
// Actualiza el título del documento
document.title = `Vous avez cliqué ${compteur} fois`;
// Función de limpieza (similar a componentWillUnmount)
return () => {
document.title = 'React App';
};
}, [compteur]); // Se ejecuta únicamente si compteur cambia
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
Gestión de eventos
React utiliza una sintaxis similar a HTML para gestionar los eventos:
function Bouton() {
function handleClick(e) {
e.preventDefault();
console.log('Le bouton a été cliqué');
}
return (
<button onClick={handleClick}>
Cliquez ici
</button>
);
}
Renderizado condicional
Puede mostrar distintos elementos en función de condiciones:
function Connexion(props) {
const estConnecte = props.estConnecte;
return (
<div>
{estConnecte ? (
<BoutonDeconnexion />
) : (
<BoutonConnexion />
)}
</div>
);
}
// Otro enfoque
function Message(props) {
const nonLu = props.messagesNonLus.length;
return (
<div>
<h1>Bonjour !</h1>
{nonLu > 0 && (
<p>Vous avez {nonLu} message(s) non lu(s).</p>
)}
</div>
);
}
Listas y claves
Para mostrar listas de elementos, utilice map() y claves únicas:
function ListeArticles(props) {
const articles = props.articles;
return (
<ul>
{articles.map((article) => (
<li key={article.id}>
{article.titre}
</li>
))}
</ul>
);
}
Gestión avanzada del estado
Context API
La Context API permite compartir datos entre componentes sin pasar por las props:
// Creación del contexto
const ThemeContext = React.createContext('light');
// Proveedor de contexto
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
// Consumo del contexto con useContext
function Bouton() {
const theme = useContext(ThemeContext);
return (
<button className={theme}>
Je suis stylisé selon le thème {theme}
</button>
);
}
useReducer para una gestión de estado compleja
useReducer es preferible a useState para estados complejos:
import { useReducer } from 'react';
// Definición del reducer
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { compteur: state.compteur + 1 };
case 'decrement':
return { compteur: state.compteur - 1 };
default:
throw new Error();
}
}
function Compteur() {
// Uso del reducer
const [state, dispatch] = useReducer(reducer, { compteur: 0 });
return (
<div>
Compteur: {state.compteur}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
Bibliotecas de gestión de estado
Para aplicaciones más complejas, puede utilizar bibliotecas específicas:
Redux
// Actions
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// Action creators
function increment() {
return { type: INCREMENT };
}
// Reducer
function compteurReducer(state = { valeur: 0 }, action) {
switch (action.type) {
case INCREMENT:
return { valeur: state.valeur + 1 };
case DECREMENT:
return { valeur: state.valeur - 1 };
default:
return state;
}
}
// Store
const store = createStore(compteurReducer);
// Componente conectado
function Compteur({ valeur, increment, decrement }) {
return (
<div>
<span>{valeur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
const mapStateToProps = state => ({
valeur: state.valeur
});
const mapDispatchToProps = {
increment,
decrement
};
export default connect(mapStateToProps, mapDispatchToProps)(Compteur);
Zustand (alternativa moderna)
import create from 'zustand';
// Creación del store
const useStore = create(set => ({
compteur: 0,
increment: () => set(state => ({ compteur: state.compteur + 1 })),
decrement: () => set(state => ({ compteur: state.compteur - 1 })),
}));
// Uso en un componente
function Compteur() {
const { compteur, increment, decrement } = useStore();
return (
<div>
<span>{compteur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
Enrutamiento con React Router
React Router permite gestionar la navegación en una aplicación React:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Accueil</Link>
<Link to="/a-propos">À propos</Link>
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
<Route path="/produits/:id" element={<DetailProduit />} />
<Route path="*" element={<PageNonTrouvee />} />
</Routes>
</BrowserRouter>
);
}
// Acceso a los parámetros de la URL
import { useParams } from 'react-router-dom';
function DetailProduit() {
const { id } = useParams();
return <h1>Détail du produit {id}</h1>;
}
Formularios en React
Formularios controlados
En un formulario controlado, React gestiona el estado del formulario:
import { useState } from 'react';
function FormulaireConnexion() {
const [email, setEmail] = useState('');
const [motDePasse, setMotDePasse] = useState('');
function handleSubmit(e) {
e.preventDefault();
console.log('Email:', email);
console.log('Mot de passe:', motDePasse);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Email:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</label>
</div>
<div>
<label>
Mot de passe:
<input
type="password"
value={motDePasse}
onChange={(e) => setMotDePasse(e.target.value)}
required
/>
</label>
</div>
<button type="submit">Se connecter</button>
</form>
);
}
Bibliotecas de formularios
Para formularios complejos, utilice bibliotecas como Formik o React Hook Form:
// Con React Hook Form
import { useForm } from 'react-hook-form';
function FormulaireInscription() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Nom</label>
<input {...register('nom', { required: 'Le nom est requis' })} />
{errors.nom && <p>{errors.nom.message}</p>}
</div>
<div>
<label>Email</label>
<input
{...register('email', {
required: 'L\'email est requis',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Adresse email invalide'
}
})}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<button type="submit">S'inscrire</button>
</form>
);
}
Optimización del rendimiento
React.memo
React.memo permite evitar renderizados innecesarios de los componentes funcionales:
const MonComposant = React.memo(function MonComposant(props) {
// Su componente
});
useMemo y useCallback
Estos hooks permiten memorizar valores y funciones:
import { useMemo, useCallback } from 'react';
function ExempleOptimisation({ a, b }) {
// Memoriza el resultado del cálculo
const resultat = useMemo(() => {
console.log('Calcul coûteux...');
return a * b;
}, [a, b]); // Recalcula únicamente si a o b cambian
// Memoriza la función
const handleClick = useCallback(() => {
console.log('Bouton cliqué avec résultat:', resultat);
}, [resultat]); // Se vuelve a crear únicamente si resultat cambia
return (
<div>
<p>Résultat: {resultat}</p>
<button onClick={handleClick}>Cliquer</button>
</div>
);
}
Lazy Loading
La carga diferida permite dividir su aplicación en fragmentos más pequeños:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
// Carga diferida de los componentes
const Accueil = lazy(() => import('./pages/Accueil'));
const APropos = lazy(() => import('./pages/APropos'));
const Contact = lazy(() => import('./pages/Contact'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Chargement...</div>}>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Tests en React
Tests unitarios con Jest y React Testing Library
// Componente que se va a probar
function Salutation({ nom }) {
return <h1>Bonjour, {nom} !</h1>;
}
// Test
import { render, screen } from '@testing-library/react';
import Salutation from './Salutation';
test('affiche le message de salutation', () => {
render(<Salutation nom="Alice" />);
const element = screen.getByText(/bonjour, alice !/i);
expect(element).toBeInTheDocument();
});
Tests de interacción
import { render, screen, fireEvent } from '@testing-library/react';
import Compteur from './Compteur';
test('incrémente le compteur lorsque le bouton est cliqué', () => {
render(<Compteur />);
// Comprobar el valor inicial
expect(screen.getByText(/compteur: 0/i)).toBeInTheDocument();
// Hacer clic en el botón
fireEvent.click(screen.getByText('+'));
// Comprobar el nuevo valor
expect(screen.getByText(/compteur: 1/i)).toBeInTheDocument();
});
Despliegue de una aplicación React
Build de producción
# Con Create React App
npm run build
# Con Vite
npm run build
Alojamiento estático
Puede desplegar su aplicación en plataformas como:
- Netlify: Arrastre y suelte la carpeta
buildo configure un despliegue continuo - Vercel: Optimizado para aplicaciones React, con despliegue automático desde GitHub
- GitHub Pages: Ideal para proyectos personales o de código abierto
- Firebase Hosting: Solución completa con autenticación y base de datos
Buenas prácticas
- Estructure su proyecto: Organice sus archivos por funcionalidad o por tipo
- Utilice componentes funcionales: Más sencillos y con mejor rendimiento gracias a los Hooks
- Evite el props drilling: Utilice Context o una biblioteca de gestión de estado
- Escriba tests: Asegúrese de que su aplicación funciona como se espera
- Optimice el rendimiento: Utilice React.memo, useMemo y useCallback con criterio
- Siga los principios SOLID: Cree componentes con una única responsabilidad
- Utilice TypeScript: Añada tipado estático para evitar errores
- Documente sus componentes: Utilice herramientas como Storybook
Conclusión
React es una biblioteca potente que permite crear interfaces de usuario modernas y de alto rendimiento. Su flexibilidad y su rico ecosistema la convierten en una excelente opción para el desarrollo de aplicaciones web de cualquier tamaño.
Si dominas los conceptos fundamentales y las buenas prácticas que se presentan en este artículo, serás capaz de crear aplicaciones React robustas, mantenibles y escalables.
Acerca de InSkillCoach
Experto en formación y tecnologías
Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.
Certificaciones:
- AWS Certified Solutions Architect – Professional
- Certificaciones de Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentarios
Los comentarios funcionan con GitHub Discussions
Inicia sesión con GitHub para participar en la discusión