El hook useMemo en React Native memoiza el resultado de los cálculos entre renderizados de componentes, evitando la ejecución repetida de operaciones costosas. A diferencia de useCallback, que memoiza una función, useMemo conserva el valor devuelto y lo recalcula solo cuando cambian las dependencias especificadas. Según React Docs, 2024, la memoización es especialmente eficaz para cálculos con arrays grandes y transformaciones complejas de datos. En React Native, cada renderizado innecesario crea una carga adicional en la conexión puente entre JavaScript y los hilos nativos, por lo que el uso correcto de useMemo afecta directamente la fluidez de las animaciones y la velocidad de respuesta de la interfaz.
Puntos clave
useMemo — es un hook de la biblioteca estándar de React, disponible en React Native sin paquetes adicionales. Memoiza el valor devuelto por la función pasada y reutiliza este valor en renderizados posteriores hasta que cambien las dependencias especificadas en el array.
El nombre del hook proviene de memoization — una técnica de optimización donde el resultado de una función costosa se almacena en caché. En llamadas posteriores con los mismos argumentos, se devuelve el valor almacenado en lugar de recalcularlo.
En el contexto de React Native, la memoización es especialmente importante debido a las características arquitectónicas. Cada renderizado de componente envía datos a través del puente JavaScript — Nativo, lo que lleva tiempo. Si un componente contiene cálculos costosos (filtrado de listas, ordenación, formato), cada renderizado los repetirá, bloqueando el hilo de JS y provocando caídas de fotogramas.
Según React Native Performance Docs, 2024, el cuello de botella no suele ser el renderizado de componentes nativos, sino la ejecución de la lógica JavaScript entre renderizados. useMemo resuelve precisamente este problema.
useMemo recibe una función y un array de dependencias, devolviendo un valor memoizado. React almacena el valor anterior y el array de dependencias. En cada renderizado, React compara las dependencias actuales con las anteriores usando Object.is. Si al menos una dependencia ha cambiado, la función se ejecuta de nuevo y el resultado se almacena.
La firma de useMemo es idéntica en la web y en React Native. El primer argumento es una función sin parámetros que devuelve el valor a memoizar. El segundo es un array de dependencias, ante cuyos cambios se recalculará el valor.
import React, { useMemo } from 'react';
const sortedList = useMemo(() => {
return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);
En este ejemplo, sortedList se recalcula solo cuando cambia la referencia al array items. Si el contenido del array cambió pero la referencia sigue siendo la misma (mutación), useMemo no detectará los cambios — esta es una limitación importante.
React utiliza el algoritmo Object.is para comparar dependencias, que funciona de manera similar a la igualdad estricta === pero maneja NaN correctamente (+0 y -0 se consideran diferentes). Esto significa que para tipos primitivos (strings, números, booleanos), la comparación funciona por valor, mientras que para objetos y arrays — por referencia.
// Object.is({'a': 1}, {'a': 1}) -> false (different refs)
// Object.is(42, 42) -> true (primitive by value)
// Object.is(NaN, NaN) -> true (correct handling of NaN)
Entender este mecanismo es crítico: si pasas un nuevo objeto en las dependencias en cada renderizado, la memoización será inútil porque las dependencias se considerarán cambiadas cada vez.
useMemo se justifica en tres escenarios: cálculos costosos, paso de props estables a componentes hijos y conservación de la identidad referencial de objetos. En React Native, los tres escenarios ocurren regularmente debido a la arquitectura de las aplicaciones móviles.
Si un componente procesa arrays grandes de datos (filtrado, ordenación, agrupación) u operaciones matemáticas intensivas, useMemo evita repetir estos cálculos en cada renderizado. En aplicaciones móviles, un ejemplo típico es formatear datos de una API antes de mostrarlos en una lista.
Cuando un componente hijo está envuelto en React.memo, solo se vuelve a renderizar cuando cambian sus props. Si un objeto prop se crea dentro del padre sin useMemo, se creará una nueva referencia en cada renderizado del padre, y el componente hijo se renderizará innecesariamente, anulando el beneficio de React.memo.
En React Native, los estilos a menudo dependen de props — por ejemplo, el ancho de un elemento se calcula según el tamaño de pantalla. useMemo permite calcular estos estilos dinámicos solo cuando cambian los parámetros de entrada.
useMemo no es una herramienta universal de optimización. En varios escenarios, no aporta beneficios e incluso puede empeorar el rendimiento debido a la sobrecarga de almacenar y comparar dependencias. En React Native, donde cada byte de memoria importa, aplicar useMemo a ciegas sin medir su efecto es un antipatrón.
El hook no aporta beneficios en tres casos principales. Primero, si el cálculo es trivial (suma simple, concatenación de strings), el costo de useMemo supera el costo del propio cálculo. Segundo, si las dependencias cambian en cada renderizado — la función se ejecutará de todos modos, y la memoización solo añade trabajo extra. Tercero, si el componente se renderiza con poca frecuencia, la sobrecarga de almacenamiento en caché no está justificada.
Según Kent C. Dodds, 2023, antes de agregar useMemo, debes medir el problema usando React DevTools Profiler o el Monitor de Rendimiento integrado en React Native. Si el renderizado de un componente toma menos de 1 ms, la memoización no es necesaria.
useMemo y useCallback — dos hooks de memoización de React que a menudo se confunden. La diferencia radica en lo que conservan: useMemo devuelve el resultado de ejecutar una función (cualquier valor), mientras que useCallback devuelve la función en sí misma. Ambos aceptan un array de dependencias, pero la sintaxis difiere.
| Característica | useMemo | useCallback |
|---|---|---|
| Devuelve | Resultado de la ejecución de la función | Referencia a la función |
| Primer argumento | Función que devuelve un valor | Función a memoizar |
| Uso típico | Almacenamiento en caché de cálculos | Callbacks estables para componentes hijos |
| Equivalencia | useMemo(() => fn, deps) | useCallback(fn, deps) === useMemo(() => fn, deps) |
En la práctica, useCallback es azúcar sintáctico sobre useMemo para los casos en que necesitas memoizar una función. En React Native, ambos hooks se usan con la misma frecuencia: useMemo — para datos (texto formateado, estilos calculados), useCallback — para manejadores de eventos (onPress, onChangeText).
Veamos dos escenarios reales de uso de useMemo en aplicaciones React Native. El primero es filtrar una lista de contactos por consulta de búsqueda, el segundo es calcular estilos dinámicos según el tamaño de pantalla.
En este ejemplo, useMemo evita el filtrado repetido de una lista grande de contactos en cada renderizado si no han cambiado ni la consulta de búsqueda ni los datos de origen.
const ContactList = ({ contacts, searchQuery }) => {
const filteredContacts = useMemo(() => {
if (!searchQuery.trim()) return contacts;
const query = searchQuery.toLowerCase();
return contacts.filter((c) =>
c.name.toLowerCase().includes(query) ||
c.phone.includes(query)
);
}, [contacts, searchQuery]);
return (
<FlatList
data={filteredContacts}
renderItem={renderContact}
keyExtractor={(item) => item.id}
/>
);
};
Sin useMemo, el filtrado se ejecutaría en cada renderizado, incluidos aquellos provocados por animaciones o cambios de estado en otras partes del componente. Con useMemo, el filtrado se ejecuta solo cuando cambian contacts o searchQuery.
En React Native, los estilos a menudo dependen de las dimensiones de la pantalla o de las props del componente. useMemo permite calcular dicho objeto de estilos una vez y reutilizarlo hasta que cambien las dependencias.
const Card = ({ title, isSelected }) => {
const cardStyle = useMemo(() => ({
backgroundColor: isSelected ? '#e3f2fd' : '#ffffff',
borderWidth: isSelected ? 2 : 1,
padding: 16,
}), [isSelected]);
return (
<View style={cardStyle}>
<Text>{title}</Text>
</View>
);
};
Este enfoque garantiza que el objeto cardStyle permanezca estable (misma referencia) hasta que isSelected cambie. Si Card está envuelto en React.memo, este patrón evita renderizados innecesarios de los elementos hijos.
Preguntas frecuentes
useMemo devuelve un valor memoizado — el resultado de ejecutar la función pasada como primer argumento. En renderizados posteriores, React devuelve el valor almacenado en caché si las dependencias no han cambiado.
useMemo devuelve el resultado de la ejecución de la función (cualquier valor: número, objeto, JSX), mientras que useCallback devuelve la función en sí misma. Ten en cuenta que useCallback(fn, deps) es equivalente a useMemo(() => fn, deps).
useMemo es inútil para cálculos triviales (suma, concatenación), renderizados poco frecuentes, dependencias que cambian en cada renderizado y tipos primitivos. Mide siempre el rendimiento antes de agregar useMemo.
Sí, si se usa innecesariamente. React almacena valores anteriores en memoria y compara dependencias en cada renderizado. Para cálculos simples, la sobrecarga de estas operaciones supera el beneficio de la memoización.
Usa React DevTools Profiler para medir los tiempos de renderizado de componentes. En React Native, también está disponible el Monitor de Rendimiento a través del menú de desarrollador. Si un renderizado toma menos de 1 ms — useMemo no es necesario.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también