8
5

More than 5 years have passed since last update.

React.memoしたコンポーネントのdisplayNameを取得する

Posted at

Reactのデバッグ用に、コンポーネントの名前を出力していたのですが、その過程でReact.memoしたコンポーネントは特殊な扱いが必要でした。

displayNameとは

以前にべからず集でも触れましたが、コンポーネントにdisplayNameがセットしてあると、それがデバッグ時にコンポーネント名として表示されます。

そして、React公式サイトにあるコード片にもWrappedComponent.displayName || WrappedComponent.nameのようなコードがあるように、関数宣言やクラスなどでnameが設定されていれば、それで代用できます。

React.memoを使った場合

ところが、React.memoを使った場合、displayNameはセットされません(もちろん関数生成ではないので、自動的にnameが付くこともありません)。なので、displayName || nameのコードでは何も取れません。

ただ、ReactのデバッグツールではMemo(WrappedComponent)のような名前がしっかりと出ています。このような名前を取得できないか調べてみました。

react-isとは

そして、調べてみると、React.memoで生成したコンポーネントにはtypeというプロパティがあって、ここにもとのコンポーネントが来ることが判明しました。あとはメモ化コンポーネントを識別できれば、要件は片付きます。

もちろん内部データにアクセスして調べられなくもないのかもしれませんが、それをやっていると将来的に内部構造が変化したときに死にます。そこでReactチームが公式に用意している手法として、react-isというライブラリがあります(GitHub)。

以下のようなメソッド・定数が用意されています。

  • ReactIs.isValidElementType(arg)argがReactコンポーネントにできるもの(タグ名の文字列・関数コンポーネント・クラスコンポーネントなど)かを判定する
  • ReactIs.typeOf(arg)argの種類を、以下の定数のどれかで返す
    • ReactIs.ConcurrentMode
    • ReactIs.ContextConsumer
    • ReactIs.ContextProvider
    • ReactIs.Element
    • ReactIs.ForwardRef
    • ReactIs.Fragment
    • ReactIs.Memo
    • ReactIs.Lazy
    • ReactIs.Portal
    • ReactIs.Profiler
    • ReactIs.StrictMode
    • ReactIs.Suspense
  • ReactIs.is***(上の定数に対応したメソッドがあります)…それぞれの種類かを判定する

なお、どういうわけかimport ReactIs from 'react-is'の形では読み込めず、import {isMemo} from 'react-is'と単品で呼ぶか、全部読み込む場合はimport * as ReactIs from 'react-is'とする必要があります。

実際に書いてみた

素材が揃ったので、あとはコードに起こすだけです。

import {isMemo} from 'react-is';

function getDisplayName(component) {
  const {name, displayName} = component;
  // displayNameがついていればそれを採用
  if(displayName) return displayName;
  // メモ化コンポーネントの場合
  if(isMemo(component)) return `Memo(${getDisplayName(component.type)})`;
  // あとはnameなどをチェック
  return name || null;
}
8
5
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
8
5