LoginSignup
0
1

More than 1 year has passed since last update.

React Hooks (メモ化のフック)

Posted at

概要

React Hooks メモ化のフックについてまとめました。

メモ化とは

ある関数の呼び出し結果を保持し、同一の呼び出し毎の再計算を防ぐ手法
Reactにおいて、必要のない子要素のレンダリングや再計算を防ぐ為に使用する。

■useCallback

関数をメモ化するためのフック

比較のためにNomalとNoneCallbackコンポーネントを用意。
上記コンポーネントはそれぞれParentの再描画が行われるたびに再描画される。
Callbackに渡すonClickはuseCallbackでラップし、
第1引数に関数、第2引数に依存配列を設定する。
useCallback()は関数の再描画の度に依存配列の値を比較し、
前回の描画時と同じ場合、メモ化している関数を返す為
空の配列の場合毎回同じになるので再描画は発生しない。

import React, { useState, useCallback } from 'react'

type ButtonProps = {
    onClick: () => void
}

// こちらは通常の関数コンポーネント
const Nomal = (props: ButtonProps) => {
    const { onClick } = props
    console.log('nomal再描画されました')

    return <button onClick={onClick}>nomal</button>
}

// こちらはメモ化した関数コンポーネント
const NoneCallback = React.memo((props: ButtonProps) => {
    const { onClick } = props
    console.log('noneCallback再描画されました')
    
    return <button onClick={onClick}>noneCallback</button>
})

// こちらはメモ化した関数コンポーネント
const Callback = React.memo((props: ButtonProps) => {
    const { onClick } = props
    console.log('callback再描画されました')
    
    return <button onClick={onClick}>callback</button>
})

export const Parent = () => {
    const [count, setCount] = useState(0)
    const nomal = () => {
        setCount((c) => c + 1)
    }
    const noneCallback = () => {
        setCount((c) => c + 1)
    }
    // useCallbackで関数をメモ化
    const callback = useCallback(() => {
        setCount((c) => c + 1)
    }, [])

    return (
        <>
            <p>Count: {count}</p>
            {/* コンポーネントに普通の関数を渡す */}
            <Nomal onClick={nomal} />
            {/* メモ化コンポーネントに普通の関数を渡す */}
            <NoneCallback onClick={noneCallback} />
            {/* メモ化コンポーネントにメモ化した関数を渡す */}
            <Callback onClick={callback} />
        </>
    )
}

export default Parent

■useMemo

値をメモ化するためのフック

第1引数に値を生成する関数、第2引数に依存配列を設定する。
useCallbackと同じく、依存配列を比較して関数の再実行を制御する。

import React, { useState, useMemo } from 'react'

export const UseMemoSample = () => {
    // テキストボックスの中身を保持
    const [text, setText] = useState('')
    // 文字列のリストを保持
    const [items, setItems] = useState<string[]>([])

    const onChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
        setText(e.target.value)
    }

    const onClickButton = () => {
        setItems((prevItems) => {
            // 現在の入力値をitemsに追加、配列を作成して保存する
            return [...prevItems, text]
        })

        // テキストボックスを空にする
        setText('')
    }

    const numberOfCharacters1 = items.reduce((sub, item) => sub + item, '')
    // useMemo使用、itemsが新しくなった時だけ関数を実行する
    const numberOfCharacters2 = useMemo(() => {
        return items.reduce((sub, item) => sub + item, '')
    }, [items])

    return (
        <>
            <p>SampleUseMemo</p>
            <div>
                <input value={text} onChange={onChangeInput} />
                <button onClick={onClickButton}>Add</button>
            </div>
            <div>
                {items.map((item, index) => (
                    <p key={index}>{item}</p>
                ))}
            </div>
            <div>
                <p>Combining Characters 1: {numberOfCharacters1}</p>
                <p>Combining Characters 2: {numberOfCharacters2}</p>
            </div>
        </>
    )
}

export default UseMemoSample
0
1
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
1