React es una biblioteca de JavaScript para construir interfaces de usuario. Utiliza un enfoque declarativo, basado en componentes reutilizables.
Introducción a React
Crear un Proyecto Nuevo
Create React App es la herramienta oficial para crear proyectos React sin configuraciones manuales.
npx create-react-app nombre-proyecto
cd nombre-proyecto
npm start
Instalación de Dependencias
npm install nombre-del-paquete
Estructura básica del proyecto
Al crear un proyecto, la estructura común incluye:
src/
- Directorio con componentes y lógica.public/
- Archivos públicos (HTML).node_modules/
- Dependencias instaladas.
JSX
JSX es una extensión de sintaxis de JavaScript que permite escribir HTML dentro de JS.
Sintaxis Básica
const elemento = <h1>Hola Mundo</h1>;
Expresiones en JSX
Puedes incluir expresiones de JavaScript dentro de llaves {}
:
const nombre = "Luis";
const elemento = <h1>Hola, {nombre}!</h1>;
Atributos
const elemento = <img src="imagen.jpg" alt="Descripción" />;
Componentes
Componente funcional
Un componente funcional es una función de JavaScript que retorna JSX.
const Componente = () => {
return <div>Este es un componente funcional.</div>;
};
Componente de clase
Componentes de clase permiten utilizar el ciclo de vida de React.
import React, { Component } from 'react';
class MiComponente extends Component {
render() {
return <h1>¡Hola desde un componente de clase!</h1>;
}
}
export default MiComponente;
Manejo de Eventos
React maneja eventos de manera similar a JavaScript, pero con algunas diferencias. Los nombres de los eventos se escriben en camelCase y debes pasar una función como valor.
const handleClick = () => {
alert('Botón clicado');
};
const MiComponente = () => (
<button onClick={handleClick}>Haz clic</button>
);
Renderizado condicional
Operadores Ternarios
const MiComponente = ({ mostrar }) => (
<div>
{mostrar ? <p>Mostrar</p> : <p>Ocultar</p>}
</div>
);
&& Operador
const MiComponente = ({ mostrar }) => (
<div>
{mostrar && <p>Mostrar</p>}
</div>
);
Colecciones
Renderizar listas
Para renderizar listas en React, utiliza el método map()
y proporciona una clave única a cada elemento.
const items = ['Elemento 1', 'Elemento 2', 'Elemento 3'];
function Lista() {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
Props y Estado
Props
Las props
(propiedades) son los datos que se pasan desde un componente padre a un hijo (para hacerlos más dinámicos y reutilizables)
function Saludo(props) {
return <h1>Hola, {props.nombre}!</h1>;
}
// Uso del componente
<Saludo nombre="Luis" />;
Propiedades Predeterminadas
Saludo.defaultProps = {
nombre: 'Desconocido',
};
State (Estado)
El hook useState
permite gestionar el estado dentro de los componentes funcionales.
import React, { useState } from 'react';
function Contador() {
const [contador, setContador] = useState(0);
return (
<div>
<p>{contador}</p>
<button onClick={() => setContador(contador + 1)}>Incrementar</button>
</div>
);
}
Estado en componentes de clase
class Contador extends React.Component {
constructor(props) {
super(props);
this.state = { contador: 0 };
}
incrementar = () => {
this.setState({ contador: this.state.contador + 1 });
};
render() {
return (
<div>
<p>{this.state.contador}</p>
<button onClick={this.incrementar}>Incrementar</button>
</div>
);
}
}
Hooks
Efectos secundarios
El hook useEffect
permite realizar efectos secundarios en componentes funcionales, como la gestión de suscripciones o la manipulación del DOM.
import React, { useEffect, useState } from 'react';
function Datos() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => setData(data));
}, []); // [] significa que el efecto se ejecuta solo una vez.
return <div>{data.length ? data[0].nombre : 'Cargando...'}</div>;
}
Desuscribir efectos
Puedes retornar una función en useEffect
para limpiar efectos (como un event listener).
useEffect(() => {
const handleResize = () => console.log(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
Uso de contextos para compartir estado
useContext
permite compartir datos entre múltiples componentes sin pasar props manualmente.
import React, { createContext, useContext } from 'react';
const TemaContext = createContext('oscuro');
function App() {
return (
<TemaContext.Provider value="claro">
<Hijo />
</TemaContext.Provider>
);
}
function Hijo() {
const tema = useContext(TemaContext);
return <div>El tema actual es {tema}</div>;
}
Manejo de estado con useReducer
useReducer
es útil para manejar estados más complejos, como en formularios.
import React, { useReducer } from 'react';
const initialState = { contador: 0 };
function reducer(state, action) {
switch (action.type) {
case 'incrementar':
return { contador: state.contador + 1 };
case 'decrementar':
return { contador: state.contador - 1 };
default:
return state;
}
}
function Contador() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>{state.contador}</p>
<button onClick={() => dispatch({ type: 'incrementar' })}>+</button>
<button onClick={() => dispatch({ type: 'decrementar' })}>-</button>
</div>
);
}
Ciclo de Vida de los Componentes
Mounting (Montaje)
Cuando el componente es agregado al DOM. Ejemplos: componentDidMount
.
Updating (Actualización)
Cuando el estado o las props cambian. Ejemplos: componentDidUpdate
.
Unmounting (Desmontaje)
Cuando el componente es removido. Ejemplos: componentWillUnmount
.
class MiComponente extends React.Component {
componentDidMount() {
console.log('Componente montado');
}
componentDidUpdate() {
console.log('Componente actualizado');
}
componentWillUnmount() {
console.log('Componente desmontado');
}
render() {
return <div>Componente con ciclo de vida</div>;
}
}
Manejo de Eventos
Agregar eventos a un componente
React normaliza eventos como onClick
, onChange
, etc.
function Boton() {
const handleClick = () => {
alert('Botón clickeado');
};
return <button onClick={handleClick}>Clic aquí</button>;
}
Manejo de Formularios
Controlar formularios en React
El estado del formulario puede manejarse usando useState
.
import React, { useState } from 'react';
function Formulario() {
const [nombre, setNombre] = useState('');
const manejarSubmit = (e) => {
e.preventDefault();
alert(`El nombre es: ${nombre}`);
};
return (
<form onSubmit={manejarSubmit}>
<input
type="text"
value={nombre}
onChange={(e) => setNombre(e.target.value)}
/>
<button type="submit">Enviar</button>
</form>
);
}
Estilos en React
Inline Styles
const estilo = { color: 'red', fontSize: '20px' };
const MiComponente = () => (
<div style={estilo}>Texto en rojo</div>
);
CSS Modules
CSS Modules permiten crear estilos locales para componentes.
import styles from './MiComponente.module.css';
function MiComponente() {
return <div className={styles.miEstilo}>Estilo con CSS Modules</div>;
}
Styled Components
Permiten escribir CSS directamente en JavaScript usando template literals.
import styled from 'styled-components';
const Boton = styled.button`
background-color: blue;
color: white;
padding: 10px;
`;
function App() {
return <Boton>Click me</Boton>;
}
React Router
Instalación de React Router
Para navegación entre páginas en una SPA (Single Page Application).
npm install react-router-dom
Configurar rutas
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
function App() {
return (
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
</Switch>
</Router>
);
}
Navegación programática
Para cambiar rutas desde código.
import { useHistory } from 'react-router-dom';
function MiComponente() {
let history = useHistory();
const navegar = () => {
history.push('/about');
};
return <button onClick={navegar}>Ir a About</button>;
}
Fetching y APIs
Fetch
Puedes usar fetch
para obtener datos de una API RESTful.
useEffect(() => {
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => console.log(data));
}, []);
Optimización
Utiliza React.memo
para memorizar componentes y useCallback
para optimizar funciones.
useMemo
import React, { useMemo } from 'react';
const MiComponente = ({ items }) => {
const calculo = useMemo(() => expensiveCalculation(items), [items]);
return <div>{calculo}</div>;
};
useCallback
import React, { useCallback } from 'react';
const MiComponente = ({ onClick }) => {
const handleClick = useCallback(() => {
onClick();
}, [onClick]);
return <button onClick={handleClick}>Clic aquí</button>;
};