Eventos en React
Hasta ahora nuestros componentes son estáticos: muestran información pero no responden a las acciones del usuario. En esta clase vamos a aprender a manejar eventos como clicks, cambios en inputs, envío de formularios, etc.
¿Qué son los eventos?
Los eventos son acciones que ocurren en el navegador:
- 👆 Click - El usuario hace clic en un botón
- ⌨️ Input - El usuario escribe en un input
- 📝 Change - El valor de un input cambia
- 📤 Submit - Se envía un formulario
- 🖱️ Hover - El ratón pasa sobre un elemento
React nos permite escuchar estos eventos y ejecutar código cuando ocurren.
Añadiendo eventos onClick
Vamos a hacer que el botón “Aplicar” responda a clicks. Todavía sin estado, solo vamos a mostrar un mensaje en la consola y una alerta.
Actualiza tu archivo react.html con este código:
function JobCard({ titulo, empresa, ubicacion, descripcion }) {
// Función que se ejecuta al hacer click
const handleAplicar = () => {
console.log('¡Click en el botón!')
console.log('Aplicando a:', titulo, '-', empresa)
alert(`Has aplicado a: ${titulo} en ${empresa}`)
}
return (
<article className="job-listing-card">
<div>
<h3>{titulo}</h3>
<small>
{empresa} | {ubicacion}
</small>
<p>{descripcion}</p>
</div>
<button className="button-apply-job" onClick={handleAplicar}>
Aplicar
</button>
</article>
)
}
¿Qué cambió?
Analicemos las novedades paso a paso.
1. Función manejadora de eventos
function JobCard({ titulo, empresa, ubicacion, descripcion }) {
// Definimos una función que se ejecuta al hacer click
const handleAplicar = () => {
console.log('¡Click en el botón!')
console.log('Aplicando a:', titulo, '-', empresa)
alert(`Has aplicado a: ${titulo} en ${empresa}`)
}
return (
<article className="job-listing-card">
{/* ... */}
<button className="button-apply-job" onClick={handleAplicar}>
Aplicar
</button>
</article>
)
}
Puntos clave:
- Definimos una función
handleAplicardentro del componente - Esta función tiene acceso a las props (
titulo,empresa) - Conectamos la función al botón con
onClick={handleAplicar}
2. Sintaxis de eventos en React
<button onClick={handleAplicar}>Aplicar</button>
Importante:
- ✅ Usa camelCase:
onClick, noonclick - ✅ Pasa la referencia a la función:
onClick={handleAplicar} - ❌ NO la llames:
onClick={handleAplicar()}← Esto ejecuta la función inmediatamente
// ✅ Correcto: pasa la referencia
<button onClick={handleAplicar}>Aplicar</button>
// ❌ Incorrecto: ejecuta la función inmediatamente
<button onClick={handleAplicar()}>Aplicar</button>
// ✅ Alternativa con función inline
<button onClick={() => alert('Click!')}>Aplicar</button>
Pruébalo
- Abre el archivo en tu navegador
- Abre la consola (F12 o Cmd+Option+I en Mac)
- Haz click en cualquier botón “Aplicar”
- Verás los mensajes en la consola y una alerta
Convención de nombres
Por convención, las funciones manejadoras de eventos suelen empezar con handle:
const handleClick = () => {
/* ... */
}
const handleSubmit = () => {
/* ... */
}
const handleChange = () => {
/* ... */
}
const handleAplicar = () => {
/* ... */
}
Esto hace el código más legible: cuando ves handleAlgo, sabes que es un manejador de eventos.
Comparación con JavaScript vanilla
Veamos cómo hemos simplificado el manejo de eventos.
Antes (JavaScript vanilla)
En nuestro archivo apply-button.js teníamos que hacer esto:
const jobsListingSection = document.querySelector('.jobs-listings')
jobsListingSection.addEventListener('click', function (event) {
const element = event.target
if (element.classList.contains('button-apply-job')) {
element.textContent = '¡Aplicado!'
element.classList.add('is-applied')
element.disabled = true
}
})
Problemas:
- ❌ Event delegation - Tenemos que escuchar en un contenedor padre
- ❌ Verificar el target - Con
if (element.classList.contains(...)) - ❌ Manipular el DOM manualmente - Cambiar texto, clases, etc.
- ❌ Código difícil de mantener - Todo mezclado
Ahora (React)
const handleAplicar = () => {
alert(`Has aplicado a: ${titulo} en ${empresa}`)
}
;<button onClick={handleAplicar}>Aplicar</button>
Ventajas:
- ✅ Directo - El evento está donde lo necesitas
- ✅ Sin querySelector - No buscas elementos
- ✅ Sin addEventListener - React lo hace por ti
- ✅ Sin event delegation - Cada componente gestiona sus eventos
- ✅ Acceso a props - La función tiene acceso al contexto del componente
¡Mucho más simple!
Eventos con funciones inline
A veces es útil definir la función directamente en el onClick:
function JobCard({ titulo, empresa }) {
return <button onClick={() => alert(`Aplicando a ${titulo}`)}>Aplicar</button>
}
¿Cuándo usar cada enfoque?
Función separada (recomendado)
function JobCard({ titulo }) {
const handleClick = () => {
console.log('Click!')
alert(titulo)
}
return <button onClick={handleClick}>Aplicar</button>
}
✅ Mejor cuando:
- La función tiene más de una línea
- Quieres reutilizar la función
- Necesitas testear la función
Función inline
<button onClick={() => alert('Click!')}>Aplicar</button>
✅ Mejor cuando:
- Es una sola línea muy simple
- No se va a reutilizar
Acceso a las props en los manejadores
Los manejadores de eventos tienen acceso completo a las props del componente:
function JobCard({ titulo, empresa, ubicacion, descripcion }) {
const handleAplicar = () => {
// Podemos usar todas las props
console.log('Título:', titulo)
console.log('Empresa:', empresa)
console.log('Ubicación:', ubicacion)
console.log('Descripción:', descripcion)
alert(`Has aplicado a ${titulo} en ${empresa}`)
}
return (
<article>
<h3>{titulo}</h3>
<button onClick={handleAplicar}>Aplicar</button>
</article>
)
}
Esto es posible gracias a los closures de JavaScript: la función handleAplicar “recuerda” las variables del ámbito donde fue creada.
Tipos de eventos comunes
React soporta todos los eventos del navegador. Los más comunes:
onClick - Click del ratón
<button onClick={() => console.log('Click!')}>Haz click</button>
onChange - Cambio en un input
<input onChange={(e) => console.log('Valor:', e.target.value)} />
onSubmit - Envío de formulario
<form
onSubmit={(e) => {
e.preventDefault()
console.log('Formulario enviado')
}}
>
<button type="submit">Enviar</button>
</form>
onMouseEnter / onMouseLeave - Hover
<div onMouseEnter={() => console.log('Entrando')} onMouseLeave={() => console.log('Saliendo')}>
Pasa el ratón
</div>
onKeyDown / onKeyUp - Teclas
<input onKeyDown={(e) => console.log('Tecla:', e.key)} />
El objeto evento (event)
Los manejadores de eventos reciben un objeto evento como parámetro:
function JobCard({ titulo }) {
const handleAplicar = (event) => {
console.log('Evento completo:', event)
console.log('Elemento que disparó el evento:', event.target)
console.log('Tipo de evento:', event.type)
}
return <button onClick={handleAplicar}>Aplicar</button>
}
Propiedades útiles del evento
const handleClick = (event) => {
event.preventDefault() // Prevenir comportamiento por defecto
event.stopPropagation() // Detener propagación del evento
event.target // Elemento que disparó el evento
event.currentTarget // Elemento al que está adjunto el evento
event.type // Tipo de evento ('click', 'change', etc.)
}
Ejemplo práctico con preventDefault
function Formulario() {
const handleSubmit = (event) => {
event.preventDefault() // Evita recargar la página
console.log('Formulario enviado')
}
return (
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Nombre" />
<button type="submit">Enviar</button>
</form>
)
}
Pasando argumentos a los manejadores
¿Qué pasa si necesitas pasar argumentos adicionales?
Opción 1: Función inline con arrow function
function JobCard({ titulo, id }) {
const handleAplicar = (jobId) => {
console.log('ID del empleo:', jobId)
}
return <button onClick={() => handleAplicar(id)}>Aplicar</button>
}
Opción 2: Con el evento
function JobCard({ titulo, id }) {
const handleAplicar = (event, jobId) => {
console.log('Evento:', event)
console.log('ID del empleo:', jobId)
}
return <button onClick={(e) => handleAplicar(e, id)}>Aplicar</button>
}
Múltiples eventos en un componente
Puedes tener varios manejadores en el mismo componente:
function JobCard({ titulo, empresa }) {
const handleAplicar = () => {
alert(`Aplicando a ${titulo}`)
}
const handleGuardar = () => {
alert(`Guardando ${titulo}`)
}
const handleCompartir = () => {
alert(`Compartiendo ${titulo}`)
}
return (
<article>
<h3>{titulo}</h3>
<button onClick={handleAplicar}>Aplicar</button>
<button onClick={handleGuardar}>Guardar</button>
<button onClick={handleCompartir}>Compartir</button>
</article>
)
}
Limitaciones actuales
Por ahora, cuando hacemos click en “Aplicar”:
- ✅ Se ejecuta la función
- ✅ Se muestra la alerta
- ✅ Se imprime en consola
- ❌ El botón NO cambia visualmente
- ❌ No se recuerda que aplicaste
¿Por qué?
Porque todavía no estamos usando estado. El componente no “recuerda” nada entre renders.
En la próxima clase aprenderemos sobre useState, que nos permitirá:
- Cambiar el texto del botón a “¡Aplicado!”
- Desactivar el botón después de aplicar
- Añadir una clase CSS
- ¡Y mucho más!
Lo que hemos aprendido de los eventos de React
- 🎯 Qué son los eventos en React
- 👆 Sintaxis de eventos -
onClick,onChange, etc. - 🔧 Crear manejadores - Funciones que responden a eventos
- 📦 Acceso a props - Los manejadores pueden usar las props
- ⚡ Comparación con vanilla JS - Mucho más simple
- 🎨 Diferentes tipos de eventos - Click, change, submit, hover, etc.
- 📝 Objeto evento - Acceder a información del evento
- 🔀 Múltiples eventos - Varios manejadores en un componente
En la próxima clase aprenderemos sobre el estado con useState, que nos permitirá crear componentes que cambian en respuesta a eventos.
💡 Recuerda: Los eventos en React usan camelCase (
onClick) y reciben referencias a funciones, no llamadas (onClick={handleClick}, noonClick={handleClick()}).