I have a vue3 project and I use the composition API. I have a component which shows some items (called tokens in this case).
<script setup>
import { ref, onMounted, toRaw } from 'vue'
import RotaryToken from './RotaryToken.vue'
const tokens = ref([])
const addToken = () => {
const id = new Date().valueOf()
tokens.value.push({ id })
}
const removeToken = (id) => {
console.log('id: ', id)
tokens.value = tokens.value.filter((token) => {
console.log('toRaw(token): ', toRaw(token))
return token.id !== id
})
console.log('tokens.value: ', tokens.value)
}
</script>
<template>
<div class="canvas">
<div class="controls"><button @click="addToken">Add token</button></div>
<div v-if="tokens.length <= 0" class="fallback-message">Place tokens here</div>
<RotaryToken
v-for="token in tokens"
:key="token.id"
@destroy="removeToken"
:id="token.id"
/>
</div>
</template>
The RotaryToken itself can emit a destroy event so I can remove itself from the array and therefore it should be removed. (I tried to self destroy a rotary token but no success).
Unfortunately I cannot remove a token from the reactive tokens
array . The problem lies somewhere in Vues Reactivity stuff.
I can see that the id is the correct one but tokens.value.filter
just does not work.
I tried with splicing instead of filtering, added nextTick
. Nothing worked.
Maybe somebody has an idea how to remove a token from the array and make it therefore rerender the template and removing destroyed tokens?
The problem is your filter test.
tokens.value.filter((token) => {
console.log('toRaw(token): ', toRaw(token))
return token.id !== id
})
where you believe id
is a number, but as your screenshot shows, it's an object called "id" but also with an id
property. So your filter test is only returning tokens where token.id !== object
Either pass the actual id
property to the function, or access the property on the object which would be id.id
:
tokens.value.filter((token) => {
console.log('toRaw(token): ', toRaw(token))
return token.id !== id.id
})