【问题标题】:React Hooks - useCallback performanceReact Hooks - useCallback 性能
【发布时间】:2019-12-11 07:33:59
【问题描述】:

我正在用 React Hooks 编写我的产品,是的,我刚接触它。

今天我对 useCallback 性能进行了数学计算。这让我考虑了很多使用 useCallback 或不使用。

让我们看看。众所周知,useCallback 用于提高性能。

function MainScreen() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState(""):

  const onAuthenticate = useCallback(() => {
    MyApi.authenticate(email, pwd);
  }, [email, pwd]);

  return <div>
    <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
  </div>;
}

在上面的示例中,假设有两个输入电子邮件和密码,那么MyCustomButton 将在电子邮件或密码更改时呈现。我尝试使用useCallback 来减少渲染次数,但对我来说还不够好。

后来想了个办法,把依赖中的email和pwd取出来,用useRef保存email和密码的值。

function MainScreen() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState(""):

  const emailRef = useRef(email);
  const pwdRef = useRef(pwd);

  const onAuthenticate = useCallback(() => {
    MyApi.authenticate(emailRef.current, pwdRef.current);
  }, []);

  useEffect(() => {
    emailRef.current = email;
    pwdRef.current = pwd;
  }, [email, pwd]);

  return <div>
    <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
  </div>;
}

使用这种方法,它会在每次电子邮件或密码更改时停止在MyCustomButton 中呈现。

它实际上在性能和成本方面更好吗?小伙伴们怎么看?

感谢分享。

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    我在您的代码中看到的问题与useCallback 无关,而与useState 有关。

    react 的一个经验法则(无论您是否使用钩子)是状态对显示的内容有直接影响。如果修改了状态,就意味着组件要重新渲染。

    这个原理是让你的组件在使用 useState 时重新渲染的原因。 React 假定 emailpassword 会改变组件的外观,因此,只要您更改其中一个值,就会重新渲染它。

    如果您在MyCustomButton 中实际上没有使用emailpwd,那么使用useRef 而不是useState 更有意义。

    但是,您在第二个代码示例中使用它的方式没有多大意义:您将 useStateuseRef 组合在一起,因此当 email 发生变化时(当您使用setEmail,然后你用相同的值更新ref。你从中得到的唯一好处是onAuthenticate不是每次都重建。

    完全跳过useState 会更有益,但从您发布的代码来看,实际上很难提出不同的解决方案,因为不清楚emailpwd 是如何/何时实际设置的.

    【讨论】:

      【解决方案2】:

      由于您只是执行 API 调用,我建议不要使用 useCallback()。改为使其成为正常功能。

      您可能正在进行过早的优化。仅当您在应用程序上执行大量计算并且需要记住您的值时,您才应该进行性能优化。

      普通函数与使用useCallback()的函数的深入比较可以从here.看到

      【讨论】:

        【解决方案3】:

        在这种情况下,我想使用 React.memo 而不是 useCallback。 使用 React.memo 确保该组件不会调用由父级封装的渲染, 一旦组件调用 render、email 或 pwd 发生变化,就不需要 useCallback

        function MainScreen() {
          const [email, setEmail] = useState("");
          const [pwd, setPwd] = useState(""):
        
          const onAuthenticate = () => {
            MyApi.authenticate(email, pwd);
          };
        
          return <div>
            <MyCustomButton onPress={onAuthenticate}>LOGIN</MyCustomButton>
          </div>;
        }
        export default React.memo(MainScreen)
        

        【讨论】:

          猜你喜欢
          • 2021-04-15
          • 1970-01-01
          • 2020-11-01
          • 2020-04-26
          • 2020-02-25
          • 2021-05-23
          • 2020-02-15
          • 2023-03-08
          • 1970-01-01
          相关资源
          最近更新 更多