LoginSignup
3
1

More than 3 years have passed since last update.

Nuxtで算出プロパティ(Computed)が更新されない問題

Posted at

どういうこと…?

Nuxt使ってる時点で、そのリアクタビリティにあぐらをかいている私たちは、時折算出プロパティ(computed)が一向に更新されない事態に出くわし、途方にくれることがあります。

今回もそうでした。firestoreで既存コメントのアップデートをリッスンしていた私は、返り値を配列にぶっこんでも更新されないことに気が付きました。

ちょっと雑に再現しますが、こんな感じ。

export default {
  data() {
    return {
      comments: [],
    },
  },
  computed: {
    filteredComments() {
      return this.comments.filter(c => !c.hidden);
    }
  },
  created() {
    this.comments = await getComments();
    firestore.collection('activities').doc('comment:update').onSnapshot({
      next: (snapshot) => {
        const data = snapshot.data();
        const index = _.findIndex(this.comments, c => c.id === data.id);
        this.comments[index] = data;
      }
    });
  }
}

「またか…」と溜息をついた私は、本腰入れて解決法を探りました。

変更が検知されてないね

で、わかったことは、Nuxt(Vue)側で、この変更を検知してないということでした。watch入れて見てみようが、this.filteredCommentsにセッターを定義して、改めて明示的に値をセットしようがダメ。

ただ、プロパティを直で入れてみると検知されます。だから、こんな感じにすれば大丈夫。

this.comments[index].hidden = data.hidden;

でも、これだとプロパティが変わった時とかいちいち手を入れなければいけなくてバグの温床技術負債となること待ったなしなので、ひとまずこうしてみた。動いた。

Object.keys(data).map(key => {
  this.comments[index][key] = data[key];
})

でも、これ、ちょっと信じがたいほどダサい。2021年に書くコードではない。そこで、きちんとドキュメントに当たりはじめました。

解決!

基本、ここに書いてあるとおりでした。

Vueのドキュメントに詳細があって、要するに、「インデックスと一緒にアイテムを直接セットする場合」は更新がリアクティブに検知されないのですね。

なので、$setを使って、このように実装してやりましょう。

this.$set(this.comments, index, data);

見事解決です。みなさん、良いVueライフを。

3
1
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
3
1