useMemo?useMemo es un Hook de React diseñado para optimizar el rendimiento de tu aplicación memorizando valores computados.
Evita cálculos innecesarios entre renderizados al cachear (memorizar) el resultado de una operación costosa.
const valorMemorizado = useMemo(() => computacionCostosa(a, b), [a, b]); arraysre-renderizados innecesarios con objetos como props.Si tienes una operación costosa que no necesita recalcularse en cada render, puedes usar useMemo para memorizar el resultado.
import React, { useState, useMemo } from 'react';
function ExpensiveCalculation() {
const [count, setCount] = useState(0);
// Memorizamos el cálculo costoso
const expensiveCalculation = useMemo(() => {
console.log("Calculando...");
return count * 2;
}, [count]); // Solo se recalcula cuando count cambia
return (
<div>
<p>Resultado costoso: {expensiveCalculation}</p>
<button onClick={() => setCount(count + 1)}>Incrementar</button>
</div>
);
} Aquí, expensiveCalculation solo se recalcula cuando count cambia.
Esto evita que el cálculo costoso se ejecute en cada renderizado.
Si tienes una lista de elementos y deseas filtrar esa lista basándote en algún criterio, puedes usar useMemo para evitar recalcular el filtro en cada render.
import React, { useState, useMemo } from 'react';
function FilteredList() {
const [filter, setFilter] = useState('');
const items = ['Venezuela', 'México', 'Colombia', 'Perú', 'Ecuador', 'Bolivia'];
// Memorizamos el resultado del filtro
const filteredItems = useMemo(() => {
return items.filter(item => item.toLowerCase().includes(filter.toLowerCase()));
}, [filter]); // Solo se recalcula cuando el filtro cambia
return (
<div>
<input
type="text"
placeholder="Filtrar países"
value={filter}
onChange={(e) => setFilter(e.target.value)}
/>
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
);
} filteredItems solo se recalcula cuando filter cambia, lo que optimiza el proceso de filtrado en grandes listas.
useMemoImagina que tienes una lista de tareas, y solo quieres mostrar aquellas que están marcadas como “completadas”.
Usando **useMemo*, puedes memorizar el resultado del filtro para evitar hacer el mismo cálculo en cada render.
import React, { useState, useMemo } from 'react';
function TaskList() {
const [showCompleted, setShowCompleted] = useState(true);
const tasks = [
{ id: 1, text: 'Comprar leche', completed: true },
{ id: 2, text: 'Estudiar React', completed: false },
{ id: 3, text: 'Hacer ejercicio', completed: true },
{ id: 4, text: 'Llamar a mamá', completed: false }
];
// Memorizamos las tareas completadas o no, dependiendo del filtro
const filteredTasks = useMemo(() => {
return tasks.filter(task => task.completed === showCompleted);
}, [showCompleted, tasks]); // Se recalcula solo cuando showCompleted o tasks cambian
return (
<div>
<button onClick={() => setShowCompleted(!showCompleted)}>
{showCompleted ? 'Ver Incompletas' : 'Ver Completas'}
</button>
<ul>
{filteredTasks.map(task => (
<li key={task.id}>{task.text}</li>
))}
</ul>
</div>
);
}
export default TaskList; useMemo para optimización de filtrado:
useMemo se utiliza para memorizar el resultado de filteredTasks. Solo se recalcula cuando el estado showCompleted o la lista de tasks cambian.useMemo, el filtrado de la lista se realizaría en cada render, lo que podría ser ineficiente, especialmente con listas grandes.showCompleted:
showCompleted cambia entre true y false, lo que activa el filtrado de las tareas completadas o no.Si un componente hijo recibe una propiedad compleja que cambia con frecuencia, puedes usar useMemo para memorizar esta propiedad y evitar renderizados innecesarios.
import React, { useState, useMemo } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const [name, setName] = useState('Juan');
// Memorizamos el objeto de propiedades
const person = useMemo(() => ({ name, count }), [name, count]);
return (
<div>
<ChildComponent person={person} />
<button onClick={() => setCount(count + 1)}>Incrementar</button>
<button onClick={() => setName('Carlos')}>Cambiar Nombre</button>
</div>
);
}
function ChildComponent({ person }) {
console.log('Renderizando Child');
return <p>{person.name} tiene {person.count} años.</p>;
} Usando useMemo, el objeto person se memoriza y solo cambia cuando name o count cambian, evitando que el componente hijo se renderice innecesariamente si los valores no han cambiado.
Si estás realizando un cálculo que depende de varias dependencias, puedes usar useMemo para evitar que se vuelva a calcular innecesariamente.
import React, { useState, useMemo } from 'react';
function PrimeNumberChecker() {
const [number, setNumber] = useState(1);
// Memorizamos el resultado de si el número es primo
const isPrime = useMemo(() => {
let isPrime = true;
for (let i = 2; i < number; i++) {
if (number % i === 0) {
isPrime = false;
break;
}
}
return isPrime;
}, [number]); // Solo se recalcula cuando number cambia
return (
<div>
<p>{number} es primo: {isPrime ? 'Sí' : 'No'}</p>
<button onClick={() => setNumber(number + 1)}>Incrementar Número</button>
</div>
);
} Aquí, el cálculo de si un número es primo se memoriza, evitando que se vuelva a realizar en cada render.
Si estás renderizando una lista grande y la paginación está controlada por el estado, puedes usar useMemo para optimizar la recalculación de los elementos que se deben mostrar en cada página.
import React, { useState, useMemo } from 'react';
function PaginatedList() {
const [page, setPage] = useState(1);
const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5', 'Item 6', 'Item 7', 'Item 8'];
const itemsPerPage = 3;
// Memorizamos los elementos que deben mostrarse en la página actual
const paginatedItems = useMemo(() => {
const startIndex = (page - 1) * itemsPerPage;
return items.slice(startIndex, startIndex + itemsPerPage);
}, [page, items]);
return (
<div>
<ul>
{paginatedItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={() => setPage(page - 1)} disabled={page === 1}>Anterior</button>
<button onClick={() => setPage(page + 1)} disabled={page * itemsPerPage >= items.length}>Siguiente</button>
</div>
);
} paginatedItems se memoriza para que solo se recalcule cuando cambie la página o los elementos, mejorando la eficiencia al manejar listas grandes con paginación.
Usar useMemo para optimizar el estilo de un componente según una propiedad (prop):
import React, { useState, useMemo } from 'react';
function Button() {
const [isActive, setIsActive] = useState(false);
// Memoriza el estilo del botón según el estado
const buttonStyle = useMemo(() => ({
backgroundColor: isActive ? 'green' : 'gray',
color: 'white',
padding: '10px 20px',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
}), [isActive]); // Solo recalcula cuando isActive cambia
return (
<button
style={buttonStyle}
onClick={() => setIsActive(!isActive)}
>
{isActive ? 'Activo' : 'Inactivo'}
</button>
);
}
export default Button; ¿Qué hace useMemo aquí?
useMemo memoriza el estilo del botón para evitar que se recalculen los estilos en cada renderizado, solo cuando el estado isActive cambie.isActive es true o false. Si el estado cambia, useMemo recalcula el estilo; de lo contrario, usa el valor previamente calculado.En este contexto, usamos useMemo para optimizar el cálculo de la suma de números mayores a un valor específico (el umbral).
Si el valor del umbral no cambia, la suma no se recalcula, lo que mejora el rendimiento evitando cálculos innecesarios en cada render.
import React, { useState, useMemo } from 'react';
function SumaCondicional() {
const [umbral, setUmbral] = useState(10); // Valor umbral
const numeros = [5, 12, 8, 20, 15, 3, 7]; // Lista de números
// Memorizamos la suma solo si el umbral cambia
const sumaNumeros = useMemo(() => {
return numeros.filter(num => num > umbral).reduce((acc, num) => acc + num, 0);
}, [umbral]); // Solo recalcular si cambia el umbral
return (
<div>
<h2>Suma de números mayores a {umbral}: {sumaNumeros}</h2>
<button onClick={() => setUmbral(umbral + 5)}>
Aumentar umbral
</button>
</div>
);
}
export default SumaCondicional; useMemo: La suma de los números solo se recalcula si el valor de umbral cambia. Si no cambia, se usa el valor previamente calculado, evitando cómputos innecesarios.useMemo optimiza el rendimiento al recalcular la suma solo cuando es necesario, evitando recalcular en cada renderizado.Este ejemplo demuestra cómo optimizar las dependencias de useMemo para evitar recalculaciones innecesarias.
En React, cuando se pasan demasiadas dependencias a useMemo, el hook se recalcula cada vez que alguna de ellas cambia, lo cual puede afectar el rendimiento.
import React, { useState, useMemo } from 'react';
function Calculadora() {
const [numero1, setNumero1] = useState(0);
const [numero2, setNumero2] = useState(0);
// Mala práctica: muchas dependencias
const suma = useMemo(() => numero1 + numero2, [numero1, numero2]);
// Buena práctica: agrupar datos en un solo objeto
const numeros = { numero1, numero2 };
const sumaOptima = useMemo(() => numeros.numero1 + numeros.numero2, [numeros]);
return (
<div>
<h2>Suma: {sumaOptima}</h2>
<button onClick={() => setNumero1(numero1 + 1)}>Incrementar Número 1</button>
<button onClick={() => setNumero2(numero2 + 1)}>Incrementar Número 2</button>
</div>
);
}
export default Calculadora; Este ejemplo muestra cómo usar useMemo de manera efectiva para evitar recalcular objetos y arrays innecesariamente en React.
// Buena práctica con objetos
const memoizedObject = useMemo(() => ({
name: user.name,
age: user.age
}), [user.name, user.age]);
// Buena práctica con arrays
const memoizedArray = useMemo(() =>
items.map(item => transformItem(item)),
[items]
); Usar useMemo en React es una excelente manera de optimizar el rendimiento cuando tienes cálculos o transformaciones costosas que no necesitan ser recalculadas en cada renderizado. Recuerda: