これはなに?
React初学者の私がフロントエンドになるための第一弾!
この記事では、ReactのhooksであるuseCallback
について学んできました!
とりあえず、useCallback
ってなんなん?
useCallback
ってなんなんということですが...
👉結論: パフォーマンス向上のためのhooksです!
ありがとうございました!!
と、いきたいところなのですが、詳細書いていきたいと思います。
useCallbackとは、関数をメモ化することができます。
メモ化とは、いわばキャッシュです。(多分)
Reactでは、親コンポーネントの再描画によって、
変更のない子コンポーネントまで再描画されてしまうことがしばしばあります。
そんな時に使うのが、useCallback
です。
では、関数をメモ化するとはいったいどういうことなのでしょう。
関数をメモ化するとは?
まず、サンプルとして以下のコードを見てみましょう。
const updateCountA1 = () => {
setCountA((prev) => prev + 1);
};
const updateCountA2 = () => {
setCountA((prev) => prev + 1);
};
Object.is(updateCountA1, updateCountA2)
上記の場合、Object.is()
の返り値は何になるでしょう。
一見、updateCountA1
とupdateCountA2
は、
まったく同一の処理を行なっているため、true
が返ってくるように思えます。
が、実際の返り値はfalse
となり、異なるオブジェクトとして判定されます。
これでは、コンポーネントが描画される度に関数が定義されてしまい、パフォーマンスの悪化に繋がります。
そこで活躍するのが、今回のuseCallback
となるわけです。
では、早速useCallbackの書き方を見ていきましょう。
useCallback
の書き方
ここでは、onClick
などで使う関数を想定してみます。
import { useCallback } from 'react'
~~~
const handleClick = useCallback(() => {
doSomething(a, b);
},[a, b]);
useCallbackはhooksなのでreact
からimport
が必要です。
では関数の構成を見ていきましょう。
const handleClick = useCallback(() => {
//第一引数 コールバック関数
doSomething(a, b);
},
//第二引数 依存配列
[a, b]);
useCallbackは以下のような構成になっています。
第一引数 コールバック関数
第一引数には実行したい関数を記述します。
今回の例でいえばonClick
で実行する関数にあたります。
doSomething(a, b)
の関数が実行されます。
第二引数 依存配列
第二引数には依存配列を記述します。
依存配列が空にする場合
依存配列は[]
のように空にすることも可能です。
const Parent = () => {
const [countA, setCountA] = useState(0);
const updateCountA = useCallback(() => {
setCountA(countA + 1);
}, []);
return (
<div>
<button onClick={updateCountA}>countup A</button>
<p>A: {countA}></p>
</div>
);
};
依存配列を空にした場合は、初回実行時に関数が定義されます。
この場合、updateCountA
内のcountA
の値は初回実行時の1
の値でメモ化されるため、
何度updateCountA
の関数を実行しても、countA
の値は1
のままとなります。
依存配列に値を入れる場合
const Parent = () => {
const [countA, setCountA] = useState(0);
const updateCountA = useCallback(() => {
setCountA(countA + 1);
}, [countA]);
return (
<div>
<button onClick={updateCountA}>countup A</button>
<p>A: {countA}></p>
</div>
);
};
依存配列に格納されている値が変化した場合のみ、関数が再定義されます。
この場合、依存配列にcountA
が格納されているため、countA
の値が更新されるたびに、
updateCountA
の関数は再定義されます。
そのため、countA
の値はカウンターの役目を果たすことができます。
実際に使ってみるZE★
useCallback
を使わない場合
import React, { useCallback, useState } from "react";
import Child from "./Child";
const Parent = () => {
console.log("親コンポーネントrendar");
const [countA, setCountA] = useState(0);
const [countB, setCountB] = useState(0);
const updateCountA = () => {
setCountA((prev) => prev + 1);
};
const updateCountB = () => {
setCountB(countB + 1);
};
return (
<div>
<button onClick={updateCountA}>countup A</button>
<Child onClick={updateCountB} />
<p>A: {countA}</p>
<p>B: {countB}</p>
</div>
);
};
import React, { useCallback, useState } from "react";
import Child from "./Child";
const Parent = () => {
import React from "react";
const Child = React.memo(({ onClick }) => {
console.log("子コンポーネントrendar");
return (
<div className="childComponent">
<button onClick={onClick}>countup B</button>
</div>
);
});
この場合、setCountA
が実行された場合でも、
子コンポーネントであるChild.js
が再描画されてしまいます。
useCallback
を使う場合
import React, { useCallback, useState } from "react";
import Child from "./Child";
const Parent = () => {
console.log("親コンポーネントrendar");
const [countA, setCountA] = useState(0);
const [countB, setCountB] = useState(0);
const updateCountA = () => {
setCountA((prev) => prev + 1);
};
// 先ほどのコードから変更はuseCallbackのみ
const updateCountB = useCallback(() => {
setCountB(countB + 1);
}, [countB]);
return (
<div>
<button onClick={updateCountA}>countup A</button>
<Child onClick={updateCountB} />
<p>A: {countA}</p>
<p>B: {countB}</p>
</div>
);
};
import React, { useCallback, useState } from "react";
import Child from "./Child";
const Parent = () => {
import React from "react";
const Child = React.memo(({ onClick }) => {
console.log("子コンポーネントrendar");
return (
<div className="childComponent">
<button onClick={onClick}>countup B</button>
</div>
);
});
useCallback
を使うことで、setCountA
が実行された場合でも、
子コンポーネントであるChild.js
は再描画されなくなります。
まとめ
useCallback
とは...?のまとめ
- 関数をメモ化することができる
- メモ化することで不要なレンダリングを防ぐことができる
- パフォーマンスを向上させることができる
useCallback
の使い方のまとめ
- 第一引数にはコールバック関数を記述する
- 第二引数には依存配列を記載する
- 依存配列は
[]
でもOK- ただし関数が定義されるのは初回実行時のみ
- 依存配列に値を格納することができる
- 格納された値が更新される度に関数が再定義される
- 依存配列は
では、良きReactライフを!!