2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

vue3 の reactive による Proxy問題

Last updated at Posted at 2021-07-14

1.reactive を使用した際に、起こった問題

vue3 になって、オブジェクトを reactive に入れるだけで、リアクティブになる。
vue2 では、Vue.set を使うシーンがあったのに比べて、ひどくシンプルになって最高。
しかし、何も考えずに reactive にしてはいけないパターンがある。

2.比較時の問題

Pure Object とでもいうべき、reactive でないオブジェクトと比べようとすると上手くいかない。

foo.ts
const foo = { bar: {} }
const foo2 = { baz: "hoge" }
const foo_reactive = reactive(foo)
foo.bar = foo2
foo_reactive.bar = foo2

console.log(foo.bar === foo2) /// true
console.log(foo_reactive.bar === foo2) /// false
console.log(foo.bar === foo_reactive.bar) /// false

普通に考えれば、reactive を通したオブジェクトなので別の実体であることは明らか。

なのだが、外部JSON 等のデータから取得して reactive なオブジェクトに格納した後で、
もとのデータと比較してしまうことがあり、 true が帰ってこない謎がなかなか解けなかった。
foo_reactive.bar というようにアクセスできてしまうのも、別オブジェクトである実感が持てず謎を呼ぶ要因となっているように思う。
(実際は、Proxy オブジェクトになっている)

なので、isEqual みたいなメソッドを作らざるを得なくなった。
大量の型の違うオブジェクトがあると、その度に作らないといけないのは非効率すぎる。

ここで重要なのは、それは reactive でないといけないのか、ということである。
computed でリアクティブ性が保たれるのであれば、reactive にする必要性はない。
vue3 ではリアクティブ性に対する視点(必要か否か)での設計は、必要不可欠だ。
(当たり前の事だが実装を優先ぎみにすると忘れがちになりそう)

3.シリアライズ問題

IndexedDb でユーザーの情報を保存しようとしたときに発覚した。

foo.ts
// IndexedDbについての記述は省略
// objectStore はオープンしたDBのオブジェクトストア
const foo = { bar: "hogehoge" }
objectStore.add(foo)  // Ok

const foo_reactive = reactive(foo)
objectStore.add(foo_reactive)  // Bad!!! #<Object> could not be cloned.

reactive なオブジェクトをそのまま put ないし add してはいけない。
Proxy オブジェクトになっているため、シリアライズできない。

じゃあ、Pure Object に変換するメソッドを作るか・・・
という力技に出てはいけない。
オブジェクトの中にオブジェクトがあると、その中のオブジェクトもPure Object に変換するメソッドが・・・となってしまう。
これも上記同様、computed ですまないかを考える必要がある。
シリアライズできない問題は、IndexedDb問わず多くありそうなので、こちらは忘れないようにしたい。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?