在 React.memo的文章有提到,每次component更新(re-evaluate)都會產生長得一模一樣的新函式物件,所以當新的函式物件當作props傳入child component,child component會因為傳入的函式物件不同而跟著parent component更新。
那要如何讓component更新時不會產生新的函式物件?
答案就是用 useCallback。
useCallback
useCallback 是React用來儲存函式物件的hook,並能保證每次component更新時使用的都是和前一次更新相同的函式,也就是同一個位址的函是物件。
// App.js (parent component)
import {useState, useCallback} from 'react';
import Me from './Me';
import Button from './Button';
export default function App(){
    console.log('App loads');
    const [isMe, setIsMe] = useState(false);
    // Use useCallback hook
    const addMe = useCallback((event) => {
    event.preventDefault();
    setIsMe((prevMe) => !prevMe);
    }, []);
    return (
        <>
            <h1>h1 always here</h1>
            <Me me={false}/>
            <Button onClick={addMe}>Click and Add Me!</Button>
        </>
    )
}
useCallback 讓component更新時不會創造一個長得一模一樣卻是儲存在不同地方的新函式,也因此每次傳入Button component的addMe函式props就會是相同的。
此外,這篇文章 在討論如何正確地用  removeEventListener 移除事件監聽器,而這個問題的原因就是每次Component更新會產生看起來名稱相同、但其實是不同物件的函式,因此沒辦法正常使用 removeEventListener。其中一個解決辦法就是用 useCallback hook;而文章下面留言有提到另一個辦法是使用useEffect來處理這個問題,而且會處理的會更好。
References
- useCallback @React Docs
 - React Hooks Tutorial - 26 - useCallback Hook
 - React - The Complete Guide (incl Hooks, React Router, Redux)
 - How to (really) remove eventListeners in React
 - 如何錯誤地使用 React hooks useCallback 來保存相同的 function instance
 - Memoization @Wikipedia
 


