0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Reactを学び始めてから2ヶ月経ったころ、ずっとおまじないと言われてきたReduxをついに教わりました。
ソースコードを見ていると、useSelectorでReduxストアからデータを取得するとき、最後におまけのような見慣れないshallowEqualという単語が書かれていました。

先輩に聞いてみると、意味自体はシンプルなのですが前提知識がないと理解が難しい内容だったのでまとめてみます。
React/JavaSctipt/TypeScriptを学び始めたばかりの、プログラミング初心者の方の参考になれば嬉しいです。

shallowEqualとは?

前提知識を整理する前に、先に結論を書きます。

  • shallowEqualはReactのReduxライブラリが用意している関数
  • オブジェクトの浅い比較を行う
  • コンポーネントの再レンダリングを防ぐために便利

shallowEqualはReactのReduxライブラリが用意している関数(ユーティリティ関数)でオブジェクトの浅い比較を行います。この浅い比較について、JavaScriptにおけるオブジェクトの比較について知らないと理解が難しいので、先にこちらを解説します。

JavaScriptにおけるオブジェクトの比較

JavaScriptにおいて、オブジェクトの比較は参照の比較をします。参照の比較とは、オブジェクトが保存されるメモリの番地(住所)を比較するということです。オブジェクトの中身を見て比較をしているわけではありません。
新しくオブジェクトを作るとメモリのどこかに保存されます。次にオブジェクトを作ると、また新しい場所に保存されます。そのオブジェクト同士の参照を比較すると、保存場所が異なるため、異なるオブジェクトと判定されます。

よって、JavaScriptでは厳密等価演算子を使って比較すると、以下のような中身が全く同じオブジェクトでもfalseと判定されます。

const object1 = {
  name: "hello",
};

const object2 = {
  name: "hello",
};

console.log(object1 === object1); // true
console.log(object1 === object2); // false

全く同じ内容のオブジェクトなのに異なるオブジェクトと判定されるのは、直感と反しますよね。ポイントは、オブジェクトの中身まで確認していない、あくまで保存場所を比較している点です。

この厳密等価演算子を使ったオブジェクトの参照が同じかどうかだけを比較する方法を、浅い比較(Shallow Comparison) と呼びます。

shallowEqualとは?

これを踏まえた上であらためてshallowEqualについて考えます。
shallowEqualはオブジェクトの浅い比較を行います。前項で説明した通り、通常の厳密等価演算子で比較をする場合、オブジェクトの中身が同じでも別のオブジェクトとみなされますが、shallowEqualを使用することで、オブジェクトの中身が一致する場合にtrue を返します。

const obj1 = { name: "hello" };
const obj2 = { name: "hello" };

console.log(obj1 === obj2); // false
console.log(shallowEqual(obj1, obj2)); // true

shallowEqualのメリット

shallowEqualを使うことで、無駄な再レンダリングを回避できます。

通常、useSelectorは Reduxストアに変更があると、それを検知してコンポーネントを再レンダリングします。ただし、全ての変更がそのコンポーネントにとって必要なわけではありません。
Reduxストアは大きな1つのオブジェクトで構成されており、reducerで新しいオブジェクトを作成すると、中身が同じであっても参照が異なります。これが、不要な再レンダリングを引き起こす原因です。
そこでshallowEqualを使用すると、中身が同じであれば同じオブジェクトとみなされるので無駄な再レンダリングを防ぐことができます。

shallowEqualの使い方

useSelectorの第2引数(比較関数)にshallowEqualを直接指定します。これにより、selectorReturningObjectが返すオブジェクトの比較にshallowEqualが適用されます。

import { shallowEqual, useSelector } from 'react-redux'

// 直接第2引数に渡す
const selectedData = useSelector(selectorReturningObject, shallowEqual)

shallowEqualの注意点と使い所

  • shallowEqualはオブジェクトの1段階目しか見ないので、ネストしたオブジェクトには使えません。階層が深いものに使用したい場合は、自分で作りましょう。
  • 基本的にuseSelectorでオブジェクトを参照するときは無駄な再レンダリングを防ぐため、shallowEqualで比較しましょう。
  • プリミティブ型(数値、文字列、真偽値など)の場合は、通常の厳密等価演算子で比較されるため、shallowEqualで比較する必要はありません。
  • 配列に対しては効果がないので注意。

終わりに

Reduxを使用する際に、useSelectorshallowEqualを組み合わせることで、不要なコンポーネントの再レンダリングを防ぐことができ、パフォーマンスの向上につながります。
useSelectorでデータを取得するときは、パフォーマンスも意識して書けるようにしましょう!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?