typescript 仅当某些钩子状态改变时才在钩子中运行帮助器函数

oknrviil  于 2022-12-24  发布在  TypeScript
关注(0)|答案(1)|浏览(116)

我想从useNumber自定义钩子返回一个helper函数,它将检查该数字是否大于传递给此函数的其他数字。
我还想重新计算这个函数的布尔结果只有当数字已经改变。
下面的代码似乎可以实现(isLargerThan只在number.value改变时运行,而不是在每次重新渲染时运行;您可以通过检查控制台日志来判断):

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 = (i: number) =>
    React.useMemo(() => {
      console.log("running isLargerThan");
      return value > i;
    }, [value]);

  return { value, isLargerThan, reset: setValue };
};

const App = () => {
  const number = useNumber();
  const [renderTrigger, setRenderTrigger] = React.useState<number>();
  return (
    <div>
      <div>Will change on each render: {getNumber()}</div>
      <div>Will change on page reload: {number.value}</div>
      <div>Larger than 50?: {String(number.isLargerThan(50))}</div>
      <button onClick={() => setRenderTrigger(getNumber())}>
        Trigger render {renderTrigger}
      </button>
      <button onClick={() => number.reset(getNumber())}>Reset number</button>
    </div>
  );
};
const rootElement = document.getElementById("root");
render(<App />, rootElement);

然而,我正在打破“钩子规则”来实现这一目标:useMemo未在顶层使用,因此出现错误:

我怎样才能做得更好?
现场示例:https://codesandbox.io/s/react-ts-playground-forked-2urxn2?file=/src/index.tsx

vbkedwbf

vbkedwbf1#

有一个非常简单的解决方案可以达到预期的效果:

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

您应该尝试useCallback,因为它 * 仅 * 在value更新时更新您传递给它的函数。

相关问题