[英]Render function only once in React
我只需要運行一次隨機數生成器(並且永遠不會重新渲染),我正在嘗試使用 useCallback 但我一定是做錯了什么,因為它沒有返回任何值。
function Editor() {
function genRandom() {
const random = Math.floor(Math.random() * (2 - 0) + 0);
return random;
}
const randomNum = useCallback(() => {
genRandom();
}, []);
console.log(randomNum);
}
export default Editor;
randomNum 根本不返回任何東西。
這是因為randomNum
是一個useCallback
返回一個 memoized function ,所以它仍然需要被調用。
function Editor() {
function genRandom() {
const random = Math.floor(Math.random() * (2 - 0) + 0);
return random;
}
const randomNum = useCallback(() => {
genRandom();
}, []);
console.log(randomNum); // <-- not invoked
}
randomNum
function 是對以下 function 定義的穩定引用:
() => {
genRandom();
}
您應該使用useMemo
而不是useCallback
來獲取記憶的隨機值。 記得返回生成的值。 我在getRandom
中沒有看到任何組件依賴項,因此您還應該在組件外部考慮它,這樣它就不會在每個渲染周期都被重新定義。
function genRandom() {
const random = Math.floor(Math.random() * (2 - 0) + 0);
return random;
}
function Editor() {
...
const randomNum = useMemo(
() => genRandom(),
[/* dependency to trigger computing new random value */]
);
...
console.log(randomNum);
...
}
export default Editor;
如果您嘗試在 React 組件內聲明genRandom
並希望提供一個穩定的回調處理程序以供稍后調用,請使用useCallback
掛鈎並記住它返回的是一個 memoized function 而不是一個值,因此 function 仍然需要被調用。
function Editor() {
...
function genRandom() {
const random = Math.floor(Math.random() * (2 - 0) + 0);
return random;
}
const randomNum = useCallback(
() => genRandom(),
[] // <-- empty dependency array
);
...
console.log(randomNum()); // <-- invoke to get random number
...
}
你可以使用這個鈎子:
function useRandomValueOnce() {
// or return React.useMemo(() => Math.floor(Math.random() * (2 - 0) + 0), []);
return React.useRef(Math.floor(Math.random() * (2 - 0) + 0)).current;
}
const randomNumber = useRandomValueOnce();
useCallback
旨在返回創建一次的 function,但是當您調用它時,它會一直運行。 要使其返回一個值,您需要一個返回語句。
useRef
保留對可變值的引用,並且只有在您指示它這樣做時才會更新。
useMemo
也一樣,只是依賴項發生了變化。
這是一個使用前面的鈎子的codesandbox 。
即使您點擊重新渲染按鈕,該值也保持不變。
您可以通過在掛鈎內使用 useMemo 並使其接受作為依賴項的參數來重新計算它來更改值。
PS:一定不能用鈎子; 您可以輕松地將這行代碼移植到您的任何組件中:
const randomValue = React.useMemo(() => Math.floor(Math.random() * (2 - 0) + 0), [])
只是為了修復代碼中實際存在的錯誤。 它沒有返回任何內容,因為您沒有在 useCallback function 參數中返回任何內容。
你需要這樣寫。 注意return getRandom();
const randomNum = useCallback(() => {
return genRandom();
}, []);
您的代碼的方式是返回未定義的,因為任何不返回任何內容的 function 都會返回 undef。 所以這就是您實際代碼中的錯誤,這就是為什么它沒有被設置。 否則我認為使用useCallback
也是正確的。
有幾種方法可以實現這一點。
最短的是懶惰的首字母 state :
function Editor() {
const [randomNum] = useState(() =>
Math.floor(Math.random() * (2 - 0) + 0)
);
console.log(randomNum);
}
useRef
將在每次渲染時返回相同的數字。 但它也會計算一個新的隨機數,並在每次渲染時將其丟棄。
useMemo
、 useCallback
和useEffect(() => {...}, [])
需要一些額外的編碼並且可能會消耗額外的資源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.