JavaScriptでカスタム要素(Custom Elements)を作成する際に発生する「Failed to execute 'define' on 'CustomElementRegistry': the name "xxx" has already been used with this registry」というエラーについて解説します。

このエラーは、同じ名前のカスタム要素を複数回定義しようとした際に発生します。カスタム要素の名前は一意である必要があり、一度定義された名前を再度使用することはできません。

エラーが発生する例

// エラーが発生するコード
customElements.define('my-element', class extends HTMLElement {});
customElements.define('my-element', class extends HTMLElement {}); // エラー発生

解決方法

1. カスタム要素の重複チェック

`customElements.get()`メソッドを使用して、要素が既に定義されているかチェックします。

if (!customElements.get('my-element')) {
  customElements.define('my-element', class extends HTMLElement {});
}

2. 一意な名前の使用

カスタム要素の名前には、必ずハイフン(-)を含める必要があります。また、プロジェクト固有のプレフィックスを使用することで、名前の衝突を防ぐことができます。

// 良い例
customElements.define('app-header', class extends HTMLElement {});
customElements.define('app-footer', class extends HTMLElement {});

3. モジュール化による管理

コンポーネントをモジュール化し、一度だけ読み込まれるようにすることで、重複定義を防ぐことができます。

// component.js
export class MyElement extends HTMLElement {
  // コンポーネントの実装
}

// エクスポートする前に定義
if (!customElements.get('my-element')) {
  customElements.define('my-element', MyElement);
}

カスタム要素定義の基本ルール

1. 要素名には必ずハイフンを含める

2. 小文字のみを使用する

3. HTMLの標準要素と重複しない名前にする

実践的な使用例

class AppHeader extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        :host {
          display: block;
          background: #f0f0f0;
          padding: 1em;
        }
      </style>
      <header>
        <h1><slot></slot></h1>
      </header>
    `;
  }
}

// 定義前にチェック
if (!customElements.get('app-header')) {
  customElements.define('app-header', AppHeader);
}

使用方法:

<app-header>My Application</app-header>

まとめ

カスタム要素の定義に関するエラーを防ぐためのポイントは以下の通りです:

  • 定義前に`customElements.get()`で既存の定義をチェックする
  • 一意な名前とプレフィックスを使用する
  • モジュール化して管理する
  • 命名規則を守る

これらの対策を実施することで、安全にカスタム要素を定義し、再利用可能なWebコンポーネントを作成することができます。