Search code examples
vue.jsnuxt.jsvuejs3nuxt3.jspinia

Attribute patch in pinia store is working from one component, but not from another (Nuxt.js)


I've those two components using Nuxt 3.

The setActive method in component 1 changes the state of activeColor, but the cancelEdit method in component 2 does not.

Any idea why this is the case?

Component 1

Here the setActive method changes activeColor:

<template>
  <div class="f-button" @click="addColor">+ Add Color</div>
  {{ activeColor }}
  <div class="f-colors">
    <Color v-for="color in colors" :color="color" :edit="activeColor === color" @click="setActive(color)"/>
  </div>
</template>

<script>
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
import Color from "~/components/Color.vue";
export default defineComponent({
  name: "ColorManagement",
  components: {Color},
  setup() {
    const projectStore = useProjectStore()
    const { getColors, getActiveColor } = storeToRefs(projectStore);
    return {
      projectStore,
      colors: getColors,
      activeColor: getActiveColor
    };
  },
  methods: {
    addColor() {
      ...
    },
    setActive(color) {
      this.projectStore.$patch({ activeColor: color })
    }
  }
});
</script>

Component 2

Here the cancelEdit method doesn't change activeColor:

  <div class="f-color">

    <div class="f-color__actions" v-if="edit">
      <div class="f-color__action" @click="cancelEdit">
        <Cancel /><span>Cancel</span>
      </div>
    </div>

  </div>

</template>

<script>
import Cancel from "~/components/icons/Cancel.vue";
import {useProjectStore} from "~/stores/projects";
import {storeToRefs} from "pinia";
export default defineComponent({
  name: "Color",
  components: {Cancel},
  props: ["color","edit"],
  setup() {
    const projectStore = useProjectStore()
    const { activeColor } = storeToRefs(projectStore);
    return {
      projectStore,
      activeColor
    };
  },
  methods: {
    cancelEdit() {
      this.projectStore.$patch({ activeColor: false })
    }
  }
});
</script> 

nuxt.config.ts

export default defineNuxtConfig({
    vite: {
        css: {
            preprocessorOptions: {
                scss: {
                    additionalData: '@use "@/assets/styles/_styles.scss" as *;'
                }
            }
        }
    },
    modules: ['@pinia/nuxt']
})

Store

import { defineStore } from "pinia";

export const useProjectStore = defineStore({
  id: 'project',
  state: () => {
    return {
      project: {
        colors: [{ color: false, name: '' }]
      },
      activeColor: null
    }
  },
  getters: {
    getColors(state){
      return state.project.colors || [];
    },
    getActiveColor(state){
      return state.activeColor;
    }
  }
});

Solution

  • Ok, if I got this correctly, the deal is this:

    Your so called Component 2 is the <Color ... component being used in Component 1, right?

    When you trigger cancelEdit inside Component 2 (aka Color) you are also triggering the logic from setActive due to this <Color ...@click="setActive(color)"...so your activeColor is set to false (from the cancelEdit method) but right after it is set to active again, got it?

    To fix this (if you don't want to change your HTML structure) you can use events stopPropagation method inside the cancelEdit:

    cancelEdit(e) {
      e.stopPropagation()
      this.projectStore.$patch({ activeColor: false })
    }
    

    Event.stopPropagation() reference