Tal vez no entendí algo, pero useCallback Hook se ejecuta cada vez que se vuelve a renderizar.
Pasé entradas, como segundo argumento para useCallback, constantes que no se cambian siempre, pero la devolución de llamada memorizada aún ejecuta mis costosos cálculos en cada render (estoy bastante seguro, puede verificarlo usted mismo en el fragmento a continuación).
He cambiado useCallback a useMemo, y useMemo funciona como se esperaba, se ejecuta cuando las entradas pasadas cambian. Y realmente memoriza los costosos cálculos.
Ejemplo en vivo:
'use strict';
const { useState, useCallback, useMemo } = React;
const neverChange = 'I never change';
const oneSecond = 1000;
function App() {
const [second, setSecond] = useState(0);
// This 👇 expensive function executes everytime when render happens:
const calcCallback = useCallback(() => expensiveCalc('useCallback'), [neverChange]);
const computedCallback = calcCallback();
// This 👇 executes once
const computedMemo = useMemo(() => expensiveCalc('useMemo'), [neverChange]);
setTimeout(() => setSecond(second + 1), oneSecond);
return `
useCallback: ${computedCallback} times |
useMemo: ${computedMemo} |
App lifetime: ${second}sec.
`;
}
const tenThousand = 10 * 1000;
let expensiveCalcExecutedTimes = { 'useCallback': 0, 'useMemo': 0 };
function expensiveCalc(hook) {
let i = 0;
while (i < tenThousand) i++;
return ++expensiveCalcExecutedTimes[hook];
}
ReactDOM.render(
React.createElement(App),
document.querySelector('#app')
);
<h1>useCallback vs useMemo:</h1>
<div id="app">Loading...</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
computedCallback = calcCallback();
.computedCallback
solo debería ser = calcCallback, it will update the callback once
neverChange` cambia.