React.Memoizationとは

<h2>Memoizationとは</h2>
コンピュータプログラムが同じ計算を繰り返さなければならない時、以前に計算した値をメモリに保存することで、<br>
同じ計算の反復実行を除去してプログラム実行速度を速くする技術です。

<h2>React.memo</h2>
reactでMemoizaitonを実現するためにはReact.memoを使います。<br>
同一のpropsでレンダリングをするならば(propsが変わっていなかったら、)、React.momoを使用し、性能向上を実現することができます。
memoを使用すれば、Reactはコンポーネントをレンダリングしないで<br>
最後にレンダリングされた結果を再利用する。

<h2>memoを使用しない場合</h2>

```react:Memo.jsx
import React, { useState } from 'react'
import { useEffect } from 'react';
import Comments from './Comments';

const commentList = [
    {title: "comment1", content: "message1", likes: 1},
    {title: "comment2", content: "message2", likes: 1},
    {title: "comment3", content: "message3", likes: 1},
];

export default function Memo() {
    const [comments, setComments] = useState(commentList);
    useEffect(() => {
        const interval = setInterval(() => {
             // functional setState, prevComment は前のstate値！
            setComments((prevComment) => [ 
                ...prevComment,
                {
                    title: `comment${prevComment.length + 1}`, 
                    content: `message1${prevComment.length + 1}`, 
                    likes: 1
                },
            ]);
        }, 1000);
        // componentがunmountする時に、returnが実行される。
        return () => {
            clearInterval(interval);
        }
    })
  return (
    <Comments commentList={comments} />
  )
}
```
Memoコンポーネントは、１秒ごとに新しいcommentListを作成して、prevComment配列に足して
Commentsコンポーネントにpropsにて渡します！

```react:Comments.jsx
import React from 'react'
import CommentItem from './CommentItem'

// 親componentからcommentList propsを受け取る。
export default function Comments({commentList}) {
  return (
    <div>
        {commentList.map(comment => <CommentItem 
            key={comment.id}
            title={comment.title}
            content={comment.content}
            likes={comment.likes}
            />
        )}
    </div>
  )
}
```
Commentsコンポーネントは、親コンポーネントから受け取ったcommentListを子コンポーネントにpropsにて
渡します。

```react:CommentItem.jsx
import React, { memo } from 'react'
import './CommentItem.css'

function CommentItem({title, content, likes}) {
   return (
    <div className="CommentItem">
        <span>{title}</span>
        <br />
        <span>{content}</span>
        <br />
        <span>{likes}</span>
        <span>{test}</span>
    </div>
  )
}
export default CommentItem;
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/7855bc50-29fe-b97f-a49d-c7394f5479c7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/0320a75a-8a00-4870-9aa9-3b9df3eefea0.png)

結果、１秒ごとに新しいコンポーネントが追加されます。
果たしてレンダの状況はどうでしょう？それが知りたい場合は、Profile APIを使えば性能チェックが可能です。
function onRenderCallbackを作成して、<Profiler>タグを性能チェックをしたいロジックを<Profiler>で囲めば終わりです。
```react:CommentItem.jsx, Profile APIを使って、性能チェックする
import React, { Profiler, memo } from 'react'
import './CommentItem.css'

function CommentItem({title, content, likes}) {
    function onRenderCallback(
        id,
        phase,
        actualDuration, 
        baseDuration,
        startTime,
        commitTime,
        interactions 
      ) {
        // レンダリング度にログを出力する！
        console.log(`actualDuration(${title}: ${actualDuration})`);
      }
   return (
    <Profiler id="CommentItem" onRender={onRenderCallback}>
        <div className="CommentItem" onClick={handleClick}>
            <span>{title}</span>
            <br />
            <span>{content}</span>
            <br />
            <span>{likes}</span>
        </div>
    </Profiler>
  )
}
export default CommentItem;
```
Provider APIを使ってレンダリングの状況を把握してみました。
その結果は、新しいCommentItemが追加されるたびに、新しいのみではなく全てのコンポーネントが
レンダリングされてしまいます。既に作成済みのcommentItemもまたレンダリングされるので
相当に非効率です。
![스크린샷 2023-02-03 00.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/b95a3c06-6d16-bec0-37b3-f8bc06cf6e6c.png)

<h2>memoを使用した場合</h2>

```react:CommentItem.jsx
export default memo(CommentItem); // memoはHCO!
```
memoの使い方は簡単です。memoはHCO(Higher Order Compoenet)として使います。
memo()にMemoizationしたいcomponentを入れます。
commentItemが１２まで作成された時点のログです。最新のコンポーネントだけがレンダリングされ
前に作成したコンポーネントはmemoにメモされ再レンダリングは発生しないことがわかります。
上記のロジックで言うと、<b>memoはCommentItemの親のpropsと同一の結果を出力するなら、それらをレンダリングせず前回のレンダリングした結果を再使用します！</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097775/fb0ab2b0-4560-c80f-45f1-fc8b3038af45.png)

React.memoは概ね以下の流れで動作します。

①コンポーネントをレンダリングする。
②①の結果をMemoizingします。
③次回のレンダリングされるもののpropsと前回のレンダリングのpropsが同じだったら、reactはMemoizingしたものを再使用し、（shallow compare）
④新しく作成されたコンポーネントのみレンダリングします。


ここで、もしオブジェクトをpropsにて渡すとどうなるでしょ！もみてみたいですね。