shanlh / vue-tinder

Have your own Tinder and TanTan.
https://shanlh.github.io/vue-tinder
MIT License
216 stars 50 forks source link

Watch `queue` from Store #47

Open Pitouli opened 2 years ago

Pitouli commented 2 years ago

I have a big issue (with Vue3): when I provide a queue with a getter of my store, the tinder breaks.

After analyzing the Tinder code, it seems that the cards are not a direct representation of the queue but of a list internally built as a copy of the queue, and updated every time the queue changes thanks to a watch on the queue.

The issue is that there is a breaking change with Vue3:

BREAKING: When watching an array, the callback will only trigger when the array is replaced. If you need to trigger on mutation, the deep option must be specified. https://v3.vuejs.org/guide/migration/watch.html#overview

https://github.com/shanlh/vue-tinder/blob/add9d84800c07af7e44d498bf79216722b303a17/src/components/vue-tinder/Tinder.vue#L220-L227

If we replace this code by the following, it works well:

watch: {
    queue: {
      handler(val) {
        const keyName = this.keyName
        const newKeys = val.map(item => item[keyName])
        const oldKeys = this.list.map(item => item[keyName])
        this.diff(newKeys, oldKeys)
      },
      deep: true
    }
}

But from what I read, "deep watchers" are the devil...

The rule is simple — do not use a deep modifier, and do not watch non-primitive-type variables at all. https://codeburst.io/5-vue-performance-tips-98e184338439

I observed that there is a update:queue event emitted every time the queue changes. It is not documented officially, but it's there. Perhaps it would be a good place to do the same diff operation?

Or perhaps, it would be even "cleaner" to simply create a method accessible on the Tinder instance, that the developper will trigger every time the queue is updated?

What do you think?

Pitouli commented 2 years ago

One solution with the Tinder View "as is", is to listen to the "update:queue" event, and to trigger an action in my store to replace the store queue with the queue received through this event. Functionally, it works, but it is strange to have to replace the store queue with the "same" queue only to trigger the watch.

Note that it works but there is a "warning" in the console for every "swipe":

Write operation failed: computed value is readonly