假設我有一個這樣的遞回回呼(但更復雜):
const weightedFactorial = useCallback(n => {
if (n === 0) {
return 1;
}
return weight * n * weightedFactorial(n - 1);
},[weight]);
有沒有辦法存盤先前計算的值,這樣如果在重復索引上呼叫該函式,就可以跳過遞回?
const value1 = weightedFactorial(60)
// Calculate recursively
const value2 = weightedFactorial(30)
// This value should already be known
// and the calculation should be skipped
我試圖保持具有已知值的狀態,但我似乎陷入了回圈,可能是因為它需要成為回呼的依賴項,
const [knownValues, setKnownValues] = useState([{ n: 0, value: 1 }]);
const weightedFactorial = useCallback(n => {
const known = knownValues.find(known => known.n === n);
if (known?.value) {
return known.value;
}
const newValue = weight * n * weightedFactorial(n - 1);
setKnownValues(knownValues => [...knownValues, { n, value: newValue }]);
return newValue;
},[knownValues, weight]);
uj5u.com熱心網友回復:
存盤記憶結果的最簡單方法是 a Map,或者如果您的函式引數是正整數,則為陣列:
function FactorialExamples(props) {
const results = [1];
const factorial = n => {
if (n in results) return results[n]; // also takes care of our base case n==0
return results[n] = n * factorial(n-1);
};
return <p>
5!: { factorial(5) }
<br />
10!: { factorial(10) }
</p>;
}
如果您factorial多次呼叫,這將很好地作業并且不會多次計算階乘。但是,它仍然會在每次渲染函陣列件時重做計算。要在重新渲染時保留結果,請將results變數從函式中移到模塊范圍內,或將其放入參考中(每個安裝的組件將存盤一次):
function Factorial(props) {
const results = useRef([1]).current;
const factorial = n => {
if (n in results) return results[n];
return results[n] = n * factorial(n-1);
};
return <p>
{props.n}!: { factorial(props.n) }
</p>;
}
function Demo() {
const [value, setValue] = useState(0);
return <div>
<input type="number" value={value} onInput=(e => setValue(e.currentTarget.valueAsNumber)} min="0" />
<Factorial n={value} />
</div>;
}
但是你有一個更復雜的情況: theweightedFactorial還取決于一個weight狀態,而不僅僅是它的引數1。您可以在每次weight更改時重置參考,但這很復雜且容易出錯。
相反,使用類似于您的 的方法useCallback,將結果存盤與“回呼”一起切換。而不是useCallback,使用useMemo并從中回傳一個閉包:
const weightedFactorial = useMemo(() => {
const results = [1];
return n => {
if (n in results) return results[n];
return weight * n * weightedFactorial(n - 1);
};
}, [weight]);
1:當然,您可以將weight和 都n視為引數,并使用標準方法來存盤具有多個引數的函式(另請參見此處)。然后結果可以再次靜態存盤或在參考中。
uj5u.com熱心網友回復:
您可以React.useMemo用來計算第一次渲染或依賴項更改時的值。但也許您指的memoization是以前計算的值不需要其他計算。
https://www.30secondsofcode.org/js/s/memoize或https://www.digitalocean.com/community/tutorials/js-understanding-recursion
您可以結合兩者useMemo,并memoization達到你所需要的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/344898.html
標籤:javascript 反应 递归 反应钩子
