useMemoの使用方法
import React, { Profiler, memo, useState } from 'react'
import './CommentItem.css'
// 親コンポーネントから渡されたpropsを受け取る
function CommentItem({title, content, likes, onClick}) {
const [clickCount, setClickCount] = useState(0);
function onRenderCallback(
// 省略・・・
) {
console.log(`actualDuration(${title}: ${actualDuration})`);
}
// componentをクリックする時に実行されるイベントハンドラー
const handleClick = () => {
// prevは前clickCount state値
setClickCount((prev)=> prev + 1);
// onClickは親コンポーネントから受け取った、useCallback hook関数!
onClick();
}
const rate = () => {
console.log("rate check");
return likes > 10 ? 'good' : 'bad';
}
return (
// profileタグで、性能チェック範囲を囲む。
<Profiler id="CommentItem" onRender={onRenderCallback}>
<div className="CommentItem" onClick={handleClick}>
<span>{title}</span>
<br />
<span>{content}</span>
<br />
<span> {likes}</span>
<br />
{/* いいね 管理*/}
<span> {rate()} </span>
<br />
<span>{clickCount}</span>
</div>
</Profiler>
)
}
export default memo(CommentItem); // memo는 HCO
コンポーネントをクリックする時に、クリックした数を管理するclickCount Stateを新しく設ける。
const [clickCount, setClickCount] = useState(0);
下は、ログです。
memoizationした前回のコンポーネントは2度とレンダリングされずに、新しく追加したコンポーネントのみログが出力されていることがわかります!rate check ログはレンダリング度に実行されるrate()のログ。
コンポーネントを押下すると、「onClick={handleClick}」により押下したコンポーネントがリレンダリングされます。
押下コンポーネントのProfileログとuseCallback hookのonClick()、rate()が呼ばれます。
useCallback hookのonClick() → pushed
rate() → rate check
その中で、rate()はlikesを演算して、その数が10を超えると'good'を、以下なら'bad'を出力します。
結局、rate()はlikesに依存しています。
しかし上のロジックでは、コンポーネントの押下は、likes値に影響を与えてないのですが、likesを評価するrate()はいつも実行されます。そのため、likes値が変わる度にlikesを評価するrate()を実行させたいですね。
これのように、rate()はlikseに依存していてlikesが変わる時だけrate()を実行させたい時にuseMemoを使います。useMemoはlikesをmemoryに保存して、likesがupdateする時にrate()が実行するようにしてくれます。
// 1番目の引数にはcallback関数を
// 2番目の引数にはdependancy arrayを定義します。
// likesがupdate → callback実行!
const rate = useMemo(()=>{
console.log("rate check");
return likes > 10 ? 'good' : 'bad';
},[likes]);
// ・・・
<span>rate:{rate} </span>
コンポーネントをクリックした時に、いいねの数を評価するrate()は、再度レンダリングされなくなったことがわかります。