Day9-React Hook 篇-认识 useCallback

今天介绍的也是避免重新渲染,使 React 效能优化的 hook useCallback。

useCallback

useCallback 的用法是将一个函式包覆并将该函式记忆起来,最後回传记忆的函式。

useCallback: 记忆的是函式
useMemo: 记忆的是函式执行後的回传值

使用原因

1. 减少子元件不必要的渲染

透过 useCallback 的记忆功能去减少子元件不必要的渲染,本文结尾的部分有范例实作这点,

一个常见对 useCallback 的误解

在 React 官方文件提到 在 render 时建立 function,Hooks 会变慢吗?,看过内容後就知道不会,因此 useCallback 不是为了解决元件内部过多内部函式导致的性能问题。

2. 弥补 React.memo 的缺点

除了可以减少不必要的渲染外,useCallback 也可以弥补 React.memo 的缺点,还记得 React.memo 是 shallow compare 吗?

透过 useCallback 可以记住 function 的记忆体位置,就可以避免 React.memo 在比较 props 值时因为"物件型别记忆体位置不同但值相同"而重新渲染的状况。

语法

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);
  • 第一个参数是 callback function
  • 第二个参数是一个阵列,此阵列不作为传到 callback function 的参数
    • useCallback(callback): 如果没有加上这个阵列,每次都会重新执行函式去产生新的函式
    • useCallback(callback, []): 空阵列的话,回传的函式不会改变
    • useCallback(callback, [...someValues]): 有加上一些元素值的话,当元素值改变时会重新更新回传的函式

范例

在 resetCount 函式加上 useCallback,使得 Child 元件不会重新渲染。

App.js

import React, { useState, useCallback } from "react";
import Child from "./Child";

const App = () => {
  const [count, setCount] = useState(0);
  console.log("re-render parent component");

  const resetCount = useCallback(() => {
    setCount(0);
  }, []);
  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount((count) => count + 1)}>Increment</button>
      <Child reset={resetCount} />
    </>
  );
};

export default App;

Child.js

import React, { memo } from "react";

const Child = memo(({ reset }) => {
  console.log("re-render child component.");
  return (
    <>
      <p>child component which resets count</p>
      <button onClick={reset}>Reset Count</button>
    </>
  );
});

export default Child;

程序码(codesandbox)


<<:  WordPress 安装 Google Analytics 教学,完整分析网站流量

>>:  Day 11基础元件

Day2-JavaScript(JS)与TypeScript(TS)的差异比较

第二天,我们来谈谈JavaScript(JS)与TypeScript(TS)的比较吧! 使用Java...

[Day20] JavaScript - Event Bubbling (事件冒泡) & Event Capturing (事件捕获)

Event Flow 事件流 DOM的Event flow概念,指的是「网页元素接收事件的顺序」。 ...

Day30 - 第一次铁人赛心得

今天是铁人赛完赛日,写一写心得吧! 老实讲自己能够完赛是真的蛮意外的,虽然一开始说是临时起意,但那也...

D-03-产生模拟资料 ? NSubstitute

如何模拟资料 在上一篇介绍完BDD以及如何在VSCode撰写BDD的测试案例以及Step之後,相信大...

Day7 NiFi - Connection

前面我们介绍完了 Processor 之後,一个完整的 Data Pipeline 就是要将这些 P...