我应该为所有功能组件应用useCallback / useMemo吗?

时间:2020-10-13 03:53:53

标签: reactjs react-native react-hooks

我有一个问题,我应该为所有功能组件的所有useCallback/ useMemo声明应用function/ variable。 据我所知, useCallback/ useMemo进行的function/ variable声明在组件更新后不再运行。这些函数/变量仅在其依赖关系更改时重新定义。它使得React的渲染工作在重新定义某些不变的东西时花费更少的精力。当这些对象更改时,它仅比较对象(功能/变量与useCallback / useMemo的依赖关系)。我认为比较工作比重新定义要快。

使用useCallback挂钩的示例:

const onOpenEnd = useCallback(() => {
    if (BTSheetRef && BTSheetRef.current) BTSheetRef.current.open()
  }, [BTSheetRef, BTSheetRef.current]);

我误解了吗?预先感谢。

2 个答案:

答案 0 :(得分:1)

不是所有的function /变量,它都应在某些情况下使用

useCallback

  • 当将回调传递给依赖于引用相等性的优化子组件以防止不必要的渲染时,这很有用。

如果在渲染父部件时不应渲染子部件,那么您必须使用此钩子,为什么?由于我们将相同的函数传递给子组件,因此不会不必要地渲染子组件。

check some code here

const ChildComponent = React.memo(() => {
  const date = new Date().getTime();
  return (
    <div>
      {date}
    </div>
  );
});

export default function App() {
  const [time, setTime] = React.useState(null);

  //if we use this one child component will rerender only if the dependacies of the useCallback gets changed,
  //when dependancies change rect will return a new function, otherwise it will retun the old function.
  const fn = React.useCallback(() => {
  }, []);

  // if we use below fn as a prop to the child, child will rerender on every rendering of this component.
  //because react will give us a new function on every renderings.
  /* 
    const fn = () => {
    } 
  */

  return (
    <div>
      <ChildComponent fn={fn}/>

      <br />
      <p>changing the numbers means that child component gets rerendered</p>
      <button onClick={() => setTime(new Date().getTime())}>change state</button>
    </div>
  );
}

useMemo

  • 您可能依赖useMemo作为性能优化,而不是语义保证。

意味着如果您必须计算大量计算,那么您应该在此挂钩上进行中继,为什么呢?只是因为计算不会在每个渲染中都执行。

check some code here

export default function App() {
  const [time, setTime] = React.useState(null);

//memorizing result of complex calculations
  const heavyComputedValue = React.useMemo(() => {
    //some heavy calculations
    let val = new Date().getTime();
    for (let a = 0; a < 1000000000; a += 1) {
      val += a;
    }

    return val;
  }, []);

//-------without memorizing results of complex calculations----------//
// enabling this will show you component update gets lagging due to calculation happens every time unnecessarily
/*
  let val = new Date().getTime();
  for (let a = 0; a < 1000000000; a += 1) {
    val += a;
  }
  const heavyComputedValue = val;
  */
//--------------------------------------------------------//

  return (
    <div>
      <p>Time: {time}</p>
      Heavy computed value: {heavyComputedValue}
      <br />
      <button onClick={() => setTime(new Date().getTime())}>
        change state
      </button>
    </div>
  );
}

答案 1 :(得分:1)

在使用useCallback和useMemo时,您仍在为每个渲染定义一个函数,这些函数只是记住您在useCallback和useMemo中定义的函数的结果,因此您不必经常运行它们。另外,当不使用useCallback或useMemo并第二次渲染组件时,定义的原始函数将被垃圾回收(释放内存空间),然后创建一个新函数。但是,使用useCallback时,原始函数将不会收集垃圾,而会创建一个新函数,因此从内存的角度来看,您的情况会稍差一些。

因此,通常最好在react组件中使用常规函数。除非您要定义的函数的运行成本很高并且您想要记住结果,否则不要使用useMemo或useCallback更为有意义。

这是一篇非常好的文章,对此进行了解释:https://kentcdodds.com/blog/usememo-and-usecallback