簡體   English   中英

僅當某些鈎子狀態發生變化時才在鈎子中運行輔助函數

[英]Run helper function in a hook only when some hook state changes

我如何調整下面的代碼,以便日志消息console.log("This should log only on resetting the number")僅在單擊“Reset number”按鈕時記錄,而不是在單擊“Rerender”按鈕時記錄?

import * as React from "react";
import { render } from "react-dom";

const getNumber = () => Math.round(Math.random() * 100);

const useNumber = () => {
  const [value, setValue] = React.useState<number>(getNumber());

  const isLargerThan = React.useMemo(() => {
    const func = (i: number) => {
      console.log("This should log only on resetting the number");
      return value > i;
    };
    return func;
  }, [value]);

  const reset = () => setValue(getNumber());

  return { value, isLargerThan, reset };
};

const App = () => {
  const number = useNumber();
  const [trigger, setTrigger] = React.useState(false);

  console.log("rerendering");

  return (
    <div>
      <div>
        Is {number.value} larger than 50?: {String(number.isLargerThan(50))}
      </div>
      <button onClick={number.reset}>Reset number</button>
      <button onClick={() => setTrigger(!trigger)}>Rerender</button>
    </div>
  );
};
const rootElement = document.getElementById("root");
render(<App />, rootElement);

實例: https ://codesandbox.io/s/react-ts-playground-forked-2urxn2?file=/src/index.tsx:305-390

據我了解,您是在渲染方法中直接調用useCallback函數,因此每次運行重新渲染時,都會再次調用該函數。 避免這種情況的一種方法是不讓您的 useMemo 返回一個函數,而是一個簡單的比較。 您還可以使用一個值來初始化您的掛鈎,以存儲您正在比較的數字,並在useMemo依賴項中使用它。 我做了一些看起來像這樣的東西,它似乎按照你的意圖工作。

const getNumber = () => Math.round(Math.random() * 100);

const useNumber = (val) => {
  const [value, setValue] = React.useState<number>(getNumber());

  const isLargerThan = React.useMemo(() => {
    console.log("This should log only on resetting the number");
    return value > val;
  }, [value, val]);

  const reset = () => setValue(getNumber());

  return { value, isLargerThan, reset };
};

const App = () => {
  const [val, setVal] = React.useState(50)
  const number = useNumber(val);
  const [trigger, setTrigger] = React.useState(false);

  console.log(number.isLargerThan)
  return (
    <div>
      <div>
  Is {number.value} larger than {val}?: {String(number.isLargerThan)}
      </div>
      <button onClick={number.reset}>Reset number</button>
      <button onClick={() => {setTrigger(!trigger)}}>Rerender</button>
    </div>
  );
};
const rootElement = document.getElementById("root");
render(<App />, rootElement);

有一個非常簡單的解決方案可以達到預期的結果:

  const isLargerThan = () =>
    React.useCallback((i: number) => {
      console.log("updating the stored function");
      return value > i;
    }, [value]);

您應該嘗試useCallback因為它只會value更新時更新您傳遞給它的函數。

暫無
暫無

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

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