🦁

【Nuxt.js】オブジェクト型のpropsを渡す時はご注意を

2020/12/09に公開

こういうことありました

ボダンのクリックメソッドにGTMイベントを発火させるのはよくある実装ですね。
今回はボタンをコンポーネントとして実装し、GTMのdatalayerにpushするオブジェクト型データをpropsとして渡そうとしたらちょっとハマったことをシェアします。

事象

あれ?propsのデフォルト値が思う通りにならないぞ?
上述通りに、GTMのデータを渡して、それをちゃんとボタンクリック時にイベントを飛ばせるのかをテストしてました。

コードは一部抜粋ですが、ボタンコンポーネントのpropsとクリックメソッドは下記の通りです。

props: {
    gtmEventData: {
      type: Object,
      default: () => {},
    },
  },
methods: {
    clickMethod(url) {
      // gtmEventDataは空ならGTMイベントを発火しない
      if (Object.keys(this.gtmEventData).length !== 0) {
        this.$gtm.push(this.gtmEventData);
      }
      window.location.href = url;
    },
  },

クリックメソッドの処理は簡単で、まずgtmEventDataは空(つまりで親から渡されず、デフォルト値がアサインされた場合)ならGTMイベントを発火しない、値があれば発火してそのままページ遷移させるという処理です。

でも実際に親からgtmEventData渡させない場合は上のコードがgtmEventDataがundefinedとが出てきてしまいます。

  • 実際の値

  • 予想の値 (デフォルト値が正常にアサインされたら)

propsにdefaultを指定したにも関わらず、なぜデフォルト値がアサインされなかったのでしょうか?

原因

ここまで読んだあなたはもうすでに気づいてたかもしれません。残念ながら当時の自分は間違ったことを気づかずに、ググってみたらはっと気づいたんです。

オブジェクト型propsのdefault値の書き方そもそも間違ったんです。

props: {
    gtmEventData: {
      type: Object,
      default: () => {}, // <= ここが間違ってます
    },
  },

上記でdefault値で {} でアサインされると思いましたが、実はこれが関数型のdefaultの書き方でした...

正しくは下記です

props: {
    gtmEventData: {
      type: Object,
      default: () => ({}), // <= 空のObjectを返す関数を指定する
    },
  },

理由は関数で返すオブジェクトではないと、オブジェクトはコピーされずに、そのまま参照されます。
ここでは詳しく書いてます

英語なのでもし読むのが面倒な方は深く考えずに、とりあえずオブジェクト型のデフォルト値を書く時必ず関数で返すようにしてください。ちなみにArray方も同じ書き方です。

最後に

アロー関数の書き方が慣れすぎてつい間違った書き方を書いちゃいますね。それでちょっと詰んでしまいました。
みなさんもpropsを指定する際に気をつけてくださいませ。
ではでは最後まで読んで頂き、ありがとうございます。
ではまた。

Discussion