簡體   English   中英

在 React 中只渲染一次 function

[英]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;

編輯 sweet-heisenberg-2uf9j

如果您嘗試在 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
  ...
}

編輯 render-function-only-once-in-react(分叉)

你可以使用這個鈎子:

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將在每次渲染時返回相同的數字。 但它也會計算一個新的隨機數,並在每次渲染時將其丟棄。

useMemouseCallbackuseEffect(() => {...}, [])需要一些額外的編碼並且可能會消耗額外的資源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM