vuejs / composition-api

Composition API plugin for Vue 2
https://composition-api.vuejs.org/
MIT License
4.19k stars 342 forks source link

reactive(new Map()); It is inconsistent with the behavior in "vue3". #771

Closed masx200 closed 3 years ago

masx200 commented 3 years ago

reactive(new Map());

It is inconsistent with the behavior in "vue3".

import VueCompositionAPI, { reactive, watch } from "@vue/composition-api";
import Vue from "vue";
Vue.use(VueCompositionAPI);
const map = reactive(new Map());
watch(
    () => map.get("a"),
    (a) => console.log(a)
);
setInterval(() => {
    map.set("a", Math.random().toString());
}, 1000);
map.set("a", 1);
console.log(map);
ygj6 commented 3 years ago

You can refer to the reply in this PR https://github.com/vuejs/composition-api/pull/509

@Aaron-Pool yeah pretty much, when doing this PR I noticed that more access to vue reactivity internals were needed, but there's no way to do that on vue 2.6, so I'm holding this for the port of composition-api to vuejs core

masx200 commented 3 years ago

But why this is not mentioned in the documentation, which is very confusing

github-actions[bot] commented 3 years ago

Stale issue message

michaelKurowski commented 2 years ago

@ygj6 As @masx200 shouldn't it be mentioned in the README? I've encountered this problem as well and first thing I've checked was the README of this project, I didn't find it there so I've assumed it was the issue with my code.

andrewvasilchuk commented 2 years ago

I have come up with this approach to make Set/Map "reactive".

// useReactiveSet.ts
import { ref, computed } from '@vue/composition-api'

export default function useReactiveSet<T>() {
  const version = ref(1)
  class ReactiveSet extends Set<T> {
    add(value: T) {
      super.add(value)
      version.value += 1
      return this
    }
  }
  const inner = ref(new ReactiveSet())

  const set = computed(() => {
    version.value
    return inner.value
  })

  return set
}