微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

这是对 useCallback 和 useMemo 的错误使用吗?

如何解决这是对 useCallback 和 useMemo 的错误使用吗?

我们什么时候应该担心函数组件重新定义变量和函数??

我认为第一种情况显然没有必要,创建函数并不昂贵(并且反应开发工具配置文件测试没有检测到 useCallback 的性能变化)

import React,{ useState,useMemo,useCallback } from "react";

export const App = () => {
  const [counter,setCounter] = useState(1);

  const showCounter = useCallback(() => {
    console.log(counter);
  },[counter]);

  return (
    <>
      <button onClick={showCounter}>Show</button>
      <button onClick={() => setCounter(counter + 1)}>Add</button>
    </>
  );
};

另一方面,在另一个示例中,使用 React 开发工具,我们可以检测到 useMemo 将渲染时间减少了一半:

import React,setCounter] = useState(1);

  const [list,setList] = useState<number[]>([]);

  function setListItem(item: number) {
    setList([...list,item]);
  }

  //should we useMemo here?
  const domList = useMemo(
    () =>
      list.map((value: number,index: number) => (
        <li key={index}> {value} </li>
      )),[list]
  );

  return (
    <>
      <p>{counter}</p>
      <button onClick={() => setCounter(counter - 1)}>Subtract</button>
      <button onClick={() => setCounter(counter + 1)}>Add</button>
      <button onClick={() => setListItem(counter)}>Push to array</button>
      <h1>List</h1>
      <ul>{domList}</ul>
    </>
  );
};

但是当我们谈论前端时,仍然不到一毫秒的增益和数组映射以及 JSX 数组并不是真正昂贵的东西。然而,在每次渲染中运行一个数组映射方法是很不舒服的。那么,我们应该怎么做呢? (让我们忘记什么时候我们有 useEffect 依赖于一些使 useMemo 变得必要的变量)

  • 在不需要在每次渲染中重新定义的所有函数和变量中的 useCallback 和 useMemo。
  • useCallback 和 useMemo 仅在我们可以清楚地看到性能提升的情况下使用(即使大多数时间都不能算作对 UX 的改进)。所以在第二个例子中我们需要 useMemo。
  • useCallback 和 useMemo 只有在特定情况下不使用它时,我们的用户体验才会大幅下降。所以只有非常昂贵的函数才会 useCallback

解决方法

您使用它们获得的性能各不相同。是的,对于 useMemo,如果您正在记忆的计算成本很高,那么它提供了明显的直接好处。但是,对于 useCallbackuseMemo,长期收益是指避免在子组件中进行不必要的渲染,而不是重新计算成本。

请记住,如果组件中的任何 props 发生变化,它们可能会触发渲染调用,并且这种情况在组件树中越高,对性能的影响就越大。这就是我们通常使用这些钩子的原因。

一般来说,组件有几个状态元素,通过备忘录钩子,我们可以建立依赖关系来避免计算冗余。例如,在您的综合案例中,您有两个状态元素:counterlist。每次 counter 更改时,您通过使其仅依赖于 domList 来防止重新计算 list。如果这是一个叶节点,肯定不会提高性能,但是,这是组件树的根,如果没有这些钩子,性能将不会随着您添加更多状态元素而扩展,您将不得不重构代码以解决性能问题。当然,如果列表中的元素超过 1000 个,<ul>{domList}</ul> 的成本可能会很高,但 <ul><ExpensiveCutie domList={domList} /></ul> 可能需要您花费数周时间进行注意、调试和重构。

简而言之,我建议在容器组件而不是叶组件中使用备忘录钩子。然而,如果您的叶组件在您实现它时变成了容器怎么办?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?