Hello!
To get to the point right of the bat.
I have two Vue components, a parent and a child. I also use Pinia for storing the state used in other components.
When I click on a layer, it selects that layer and put it in the Pinia store. If I click on another layer, it selects this layer and add it to the Pinia store, right after it clears the state in the Pinia store (this.data = []).
If I want to get the selected state of the Layer component within that component from my Pinia store with:
layers.selected(layer.id)
this forces to rerender the layer component everytime theres a change in the Pinia store. I mean, ofc the state should change so I can change the class of the layer component based on its selected state, but i'm also using a library to move these layers around and their changed position gets reverted when I deselect the layer after moving it.
It only happens if I render the state from the Pinia store within the component. I might have forgotten about how to tackle the rendering of components in Vue, but my mind is mushy after severalt tries with computed properties and so forth that I just can see a solution right now.
Here's my code (i left out a lot of other things that I use to move around the layers and such to keep it simple):
Parent (Canvas.vue):
<template>
<div class="flex items-center justify-center w-full h-full overflow-scroll">
<layer
v-for="layer in project.layers"
:key="layer.id"
:layer="layer"
@mousedown.exact.stop="layers.select(layer.id)"
/>
</div>
</template>
<script setup>
import Layout from '@/Layouts/AppLayout.vue'
import Layer from '@/Components/Layer.vue'
import { useLayersStore } from '@/stores/LayersStore';
defineOptions({ layout: Layout })
const props = defineProps(['project'])
const layers = useLayersStore();
</script>
Child (Layer.vue):
<template>
<div :data-id="layer.id" :data-x="layer.x" :data-y="layer.y" :style="layerStyle" :class="layerClass">
<img src="/man.png" class="h-32 w-32 mb-3">
{{ layer.text }}
</div>
</template>
<script setup>
const props = defineProps(['layer'])
import { computed } from 'vue'
import { useLayersStore } from '@/stores/LayersStore';
const layers = useLayersStore();
const layerStyle = computed(() => ({
width: `${props.layer.width}px`,
height: `${props.layer.height}px`,
transform: `translate(${props.layer.x}px, ${props.layer.y}px)`,
}));
const layerClass = computed(() => [
'drag-resize absolute select-none flex flex-col items-center justfiy-center h-12 w-12 border border-neutral-300 hover:border-blue-500 p-2 bg-white',
layers.selected(props.layer.id) ? 'ring-2 ring-offset-2 ring-blue-500' : '',
]);
</script>
Pinia store:
import { defineStore } from 'pinia';
export let useLayersStore = defineStore('selected', {
state(){
return {
data: []
};
},
actions: {
selected(id){
return this.data.includes(id);
},
select(id){
if(this.data.includes(id)){
return
}
this.data = [],
this.data.push(id);
},
clear(){
this.data = [];
}
},
});