LoginSignup
0
0

More than 1 year has passed since last update.

React.Memoizationとは

Last updated at Posted at 2023-02-02

Memoizationとは

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

React.memo

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

memoを使用しない場合

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コンポーネントは、1秒ごとに新しいcommentListを作成して、prevComment配列に足して
Commentsコンポーネントにpropsにて渡します!

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にて
渡します。

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
image.png

結果、1秒ごとに新しいコンポーネントが追加されます。
果たしてレンダの状況はどうでしょう?それが知りたい場合は、Profile APIを使えば性能チェックが可能です。
function onRenderCallbackを作成して、タグを性能チェックをしたいロジックをで囲めば終わりです。

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

memoを使用した場合

CommentItem.jsx
export default memo(CommentItem); // memoはHCO!

memoの使い方は簡単です。memoはHCO(Higher Order Compoenet)として使います。
memo()にMemoizationしたいcomponentを入れます。
commentItemが12まで作成された時点のログです。最新のコンポーネントだけがレンダリングされ
前に作成したコンポーネントはmemoにメモされ再レンダリングは発生しないことがわかります。
上記のロジックで言うと、memoはCommentItemの親のpropsと同一の結果を出力するなら、それらをレンダリングせず前回のレンダリングした結果を再使用します!
image.png

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

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

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0