Props with type Object/Array must use a factory function to return the default value

Props with type Object/Array must use a factory function to return the default value:

あなたがこの記事を見ているということは、コンソールに以下のワーニングが出ていることでしょう。


WARN

[Vue warn]: Invalid default value for prop "XXX": Props with type Object/Array must use a factory function to return the default value. 
このワーニングはVueコンポーネントのpropsに関するものです。

「propsのdefaultの値にObjectやArrayを使用したい場合、ファクトリー関数を指定しろ」

という内容のワーニングです。


ワーニングを解消する

以下のようにコードを修正することでワーニングを解消できます。


修正前

props: { 
  obj: { 
    type     : Object, 
    require  : false, 
    'default': { count: 0 } // Objectをそのまま指定している 
  }, 
} 


修正後

props: { 
  obj: { 
    type     : Object, 
    require  : false, 
    'default': () => ({ count: 0 }) // Objectを生成する関数を指定する 
  }, 
} 


なぜ関数を指定する必要があるのか

なぜ、ObjectやArrayをデフォルト値としたい場合、関数を指定する必要があるのでしょうか。


ワーニングを無視すると何が起こるか

まず、ワーニングを無視した場合に何が起こるのか試してみます。

AppCounter.vue
<template> 
  <div class="content"> 
    <span>{{ obj.count }}</span> 
    <button @click="obj.count++;">+1</button> 
  </div> 
</template> 
 
<script> 
export default { 
  props: { 
    obj: { 
      type: Object, 
      require: false, 
      'default': { count: 0 } // ワーニングを無視して、Objectをそのまま指定している 
    } 
  } 
}; 
</script> 
「+1」ボタンのクリックでカウンターをインクリメントする、Vueコンポーネントです。

App.vue
<template> 
  <div id="app"> 
    <app-counter /> 
    <app-counter /> 
  </div> 
</template> 
 
<script> 
import AppCounter from "./components/AppCounter"; 
 
export default { 
  name: "App", 
  components: { 
    AppCounter 
  } 
}; 
</script> 
そのカウンターを2つ配置して動かしてみると、以下のような結果になります。


counter01.gif


どちらのボタンをクリックしても、2つのカウンターがインクリメントされています。

↓のリンクから実際に触っていただけます。
Edit Vue Template


オブジェクトや配列は値がコピーされず、参照が共有される

propsのデフォルト値に指定したオブジェクトや配列は、値がコピーされることなく参照が共有されます。

そのため、複数のvueインスタンスが同一のObjecを参照し、同一のObjectに変更を加えてしまう状況が発生します。

2つのカウンターがどちらのボタンの操作でもインクリメントされるのは、このためです。

ワーニングを出すのではなく、フレームワーク側でObjectや配列を自動でディープコピーしてくれればいいのでは?と考えることもできるのですが、開発者側で

ファクトリー関数を指定できるようにすることで、ディープコピーにまつわるリスクを抑えつつ、実装の選択肢を広げ自由度を上げる目的があるようです。


参考

https://github.com/vuejs/vue/issues/1032

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)