[Vue3] dataオブジェクトに後からプロパティを追加する時の注意点


すごい簡単だけど困ったのでメモしておきます。

dataオブジェクトの初期値を外部APIから入れようとした

Vue.jsを用いたプロフィール入力画面で、Firestoreから既存のプロフィール情報を引っ張ってくるようにしています。
1つずつプロフィール情報をdataオブジェクトに割り当てていくのは面倒なので、ドキュメントオブジェクトを全部dataオブジェクトに全部つっこもうとして初期値が反映されず困っていました。
コードは以下の通り。

//-- abbr --
  data () {
    return {
    }
  },
  mounted() {
    this.$data = { ...this.getProfile(getAuth().currentUser.uid)};
  },
  methods: {
    const getProfile = async (uid) => {
      const docRef = doc(getFirestore(), "users", uid);
      const docSnap = await getDoc(docRef);
      if(docSnap.exists()){
        return docSnap.data();
      }
    };
  },
//-- abbr --

こんなの。

ルートのdataオブジェクトにリアクティブなプロパティの追加はできないらしい

参考:Vue3 公式ドキュメント

一度監視されると、ルートのデータオブジェクトにリアクティブなプロパティを追加することはできなくなります。そのため、インスタンスを作成する前に、すべてのルートレベルのリアクティブプロパティを前もって宣言しておくことをお勧めします。

この表現だけだとわからず、読み飛ばしていました。

解決:前もってプロパティを宣言しておく

//-- abbr --
  data(){
    return {
      user: "",
    }
  },
  mounted() {
    this.user = { ...this.getProfile(getAuth().currentUser.uid)};
  },
  methods: {
    const getProfile = async (uid) => {
      const docRef = doc(getFirestore(), "users", uid);
      const docSnap = await getDoc(docRef);
      if(docSnap.exists()){
        return docSnap.data();
      }
    };
  },
//-- abbr --

dataオブジェクトの返り値のとこに、前もってuserプロパティを宣言しておき、そこにFirestoreから取得したドキュメントオブジェクトを突っ込むとよいらしい。

もしくは、こういう表記もありかもしれない。(試してない)

//-- abbr --
  data(){
    this.user = { ...this.getProfile(getAuth().currentUser.uid)}; 
    return {
    }
  },
//-- abbr --

ルートレベルのリアクティブプロパティはこれで正解?

ルートレベルのリアクティブプロパティ

がこれで正解かは自信ないけど、こうすると確かに想定した通りの挙動になったので合ってそう。
Firestoreからドキュメントオブジェクトを入れたい時だけでなく、jsonから出力したい時とか使えそうです。