7.3-funcion tipo fleha 2
Funciones Flecha vs Funciones Normales en React
Diferencias Principales
1. Sintaxis
javascript
// Función normal
function sumar(a, b) {
return a + b;
}
// Función flecha
const sumar = (a, b) => {
return a + b;
}
// Función flecha con return implícito (una línea)
const sumar = (a, b) => a + b;
2. Contexto de this (¡LA DIFERENCIA MÁS IMPORTANTE!)
javascript
// Ejemplo con función normal
class ComponenteNormal {
constructor() {
this.valor = 10;
}
metodoNormal() {
console.log(this.valor); // 'this' se refiere a la instancia
}
}
// Ejemplo con función flecha
class ComponenteFlecha {
constructor() {
this.valor = 10;
// La función flecha captura el 'this' del contexto donde se define
this.metodoFlecha = () => {
console.log(this.valor); // 'this' siempre será el de ComponenteFlecha
};
}
}
¿Por qué se usa solo el nombre en los eventos?
Ejemplo 1: Evento onClick
javascript
function BotonEjemplo() {
// CORRECTO: Solo pasamos la referencia
const handleClick = () => {
console.log('Botón clickeado!');
};
return (
<button onClick={handleClick}> {/* ← Solo el nombre, sin paréntesis */}
Haz clic
</button>
);
}
¿Por qué NO usar paréntesis?
javascript
function BotonIncorrecto() {
const handleClick = () => {
console.log('Botón clickeado!');
};
return (
{/* ❌ INCORRECTO: Se ejecuta inmediatamente al renderizar */}
<button onClick={handleClick()}>
Haz clic
</button>
{/* ✅ CORRECTO: Se pasa la referencia para ejecutar luego */}
<button onClick={handleClick}>
Haz clic
</button>
);
}
Ejemplos Prácticos Completos
Ejemplo 1: Formulario con múltiples eventos
javascript
function FormularioContacto() {
const [formData, setFormData] = useState({
nombre: '',
email: '',
mensaje: ''
});
// Función flecha para manejar cambios
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
// Función flecha para submit
const handleSubmit = (e) => {
e.preventDefault();
console.log('Datos enviados:', formData);
// Aquí iría la lógica para enviar al servidor
};
// Función normal (también funciona, pero cuidado con 'this')
function handleReset() {
setFormData({ nombre: '', email: '', mensaje: '' });
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="nombre"
value={formData.nombre}
onChange={handleChange} // ← Solo referencia
placeholder="Tu nombre"
/>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange} // ← Solo referencia
placeholder="Tu email"
/>
<textarea
name="mensaje"
value={formData.mensaje}
onChange={handleChange} // ← Solo referencia
placeholder="Tu mensaje"
/>
<button type="submit">Enviar</button>
<button type="button" onClick={handleReset}> {/* ← Solo referencia */}
Limpiar
</button>
</form>
);
}
Ejemplo 2: Lista con eventos dinámicos
javascript
function ListaTareas() {
const [tareas, setTareas] = useState([
{ id: 1, texto: 'Aprender React', completada: false },
{ id: 2, texto: 'Practicar hooks', completada: true },
{ id: 3, texto: 'Crear proyecto', completada: false }
]);
// Función flecha para alternar estado
const toggleCompletada = (id) => {
setTareas(tareas.map(tarea =>
tarea.id === id
? { ...tarea, completada: !tarea.completada }
: tarea
));
};
// Aquí necesitamos una función que devuelva otra función
return (
<ul>
{tareas.map(tarea => (
<li key={tarea.id}>
<span style={{
textDecoration: tarea.completada ? 'line-through' : 'none'
}}>
{tarea.texto}
</span>
{/* ✅ CORRECTO: Pasamos una función que devuelve la ejecución */}
<button onClick={() => toggleCompletada(tarea.id)}>
{tarea.completada ? 'Desmarcar' : 'Completar'}
</button>
{/* ❌ INCORRECTO: Se ejecutaría inmediatamente */}
{/* <button onClick={toggleCompletada(tarea.id)}>Completar</button> */}
</li>
))}
</ul>
);
}
Ejemplo 3: Diferencia en componentes de clase
javascript
class ContadorClase extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
// Necesitamos bindear en constructores con funciones normales
this.incrementarNormal = this.incrementarNormal.bind(this);
}
// Función normal - necesita bind para conservar 'this'
incrementarNormal() {
this.setState({ count: this.state.count + 1 });
}
// Función flecha - automáticamente captura 'this'
incrementarFlecha = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Contador: {this.state.count}</p>
{/* Con función normal (necesita bind) */}
<button onClick={this.incrementarNormal}>
Incrementar (normal)
</button>
{/* Con función flecha (no necesita bind) */}
<button onClick={this.incrementarFlecha}>
Incrementar (flecha)
</button>
{/* Otra alternativa: arrow function en el evento */}
<button onClick={() => this.incrementarNormal()}>
Incrementar (inline)
</button>
</div>
);
}
}
Reglas de Oro en React
Siempre pasa solo el nombre de la función a los eventos: onClick={handleClick}
Usa funciones flecha para evitar problemas con this
Si necesitas pasar parámetros, usa arrow function inline:
javascript
onClick={() => funcionConParametro(parametro)}
Para componentes de clase, prefiere funciones flecha en propiedades
¿Cuándo usar cada una?
Resumen Final
javascript
// ✅ RECOMENDADO EN REACT
const Componente = () => {
const manejarEvento = (parametro) => {
// Lógica aquí
};
return (
<button onClick={() => manejarEvento('valor')}>
Acción
</button>
);
};
// ⚠️ Menos común hoy día (en componentes de clase)
class ComponenteClase extends React.Component {
manejarEvento = (parametro) => {
// Lógica aquí
};
render() {
return (
<button onClick={() => this.manejarEvento('valor')}>
Acción
</button>
);
}
}
La clave está en entender que los eventos en React esperan una referencia a una función, no el resultado de ejecutarla. Por eso usamos onClick={funcion} y no onClick={funcion()}
Comentarios
Publicar un comentario