概要
配列データをstateに持つ親コンポーネントの子として、配列の各要素に依存する子コンポーネントがあるときに、更新した配列要素に依存する子コンポーネントだけを再描画させるためのコーディング方法をメモ。useMemo, useCallbackを用いる。
詳細
があるとき、目的の動作をさせるには、
SampleをMemo化する
必要がある。さらに、Sampleが依存するデータに関数が含まれる場合は、
関数をuseCallbackを使って囲む
必要がある。上記の2点を施し、目的の動作をさせるためのコードを記載する。
準備
- 必要なものをimport
- 後で使うtypeを定義しておく
'use client'; import { useState, useCallback, memo, FC } from "react"; type SampleDataType = { name: string; obj: { objName: string; } } type SampleProps = { index: number; data: SampleDataType; updateData: (index: number, item: SampleDataType) => void; }
Sample
- MemoSample: Sampleをメモ化
- ボタンを押したときに、自身が依存するデータを書き換えるため、propsで渡ってきた更新関数props.updateDataを呼ぶ
- 後述のSampleArrayにて、props.updateDataにわたってくる関数はuseCallbackで囲まれている
- なお、デバッグ用にconsole.logを仕込んでおく
const Sample: FC<SampleProps> = (props: SampleProps) => { console.log(`Sample ${props.index} ${props.data.name} ${props.data.obj.objName}`); const onClick = () => { const newData = { ...props.data, name: `test${props.index}1`, obj: { objName: `obj${props.index}1` } }; props.updateData(props.index, newData); } return ( <> <span>{props.data.name}</span><button onClick={onClick}>変更</button> </> ); } // メモ化 const MemoSample = memo(Sample);
配列データをstateに持つ親コンポーネント
- 配列のデータarrayDataは、実験用に300個の要素を持たせてある
- 配列内の指定したインデクスの要素を更新する関数updateArrayItemを、useCallbackで囲んだ形で定義する
- updateArrayItemを、Sampleで呼び出せるようにするため、Sampleのpropsに渡す
- なお、デバッグ用にconsole.logを仕込んでおく
ポイント2: useCallbackで、
const SampleArray: FC = () => { console.log(`SampleArray`); // 配列のデータ const [arrayData, setarrayData] = useState( Array.from({ length: 300 }, (_, i) => ({ name: `test${i}`, obj: { objName: `obj${i}` } })) ); // 配列のインデクスを指定して更新する関数 // useCallbackで囲っておく const updateArrayItem = useCallback((index: number, item: SampleDataType) => { setarrayData((prevarrayData) => prevarrayData.map((x, i) => (i === index ? item : x))); }, []); return ( <div> {arrayData.map( (data: SampleDataType, index: number) => <> <MemoSample key={index} index={index} data={data} updateData={updateArrayItem} /> {(index + 1) % 10 === 0 && <br />} </> )} </div> ); }
動作確認
まず、コンポーネントを表示させると以下のようになる。

このとき、デバッグ用に仕込んだconsole.logにより以下の出力となり、親コンポーネントと、300個の子コンポーネントが描画される。
SampleArray page.tsx:18 Sample 0 test0 obj0 : page.tsx:18 Sample 299 test299 obj299
ここで、113番のボタンを押すと以下のログが出た。すなわち、更新したコンポーネントだけが再描画されている。
![]()
page.tsx:37 SampleArray page.tsx:18 Sample 113 test1131 obj1131