Search code examples
javascriptvue.jsvuejs3pinia

Pinia issue with array inside object


My pinia store inside a vue3 app, contains a currentReservation object with a pricings array property.

Each pricing got a property id and quantity, when i add a pricing is added inside the store & component, same for the quantity (can be increase or decrease).

But when i removed a pricing inside the store, inside decreaseReservationPricing if the quantity is 0. The store is updated, but inside my component the storePricings property is not removed. The quantity is update, but each object stay there.

Note the fact that if i have added two pricing, when i removed one, inside the component i still got two (everything works fine inside the store).

There is my component script:

<script setup lang="ts">
import { computed } from 'vue'
import { Pricing, ReservationPricing } from '@/@types/base'

import formsUiBlock from '@/components/forms/ui/Block.vue'
import CardsPricingItem from '@/components/cards/PricingItem.vue'

import { useReservationStore } from '@/stores/modules/reservation'

defineOptions({
  name: 'FormsBooking',
})

defineProps<{ pricings: Pricing[] }>()

const reservationStore = useReservationStore()
const storePricings = computed(() => reservationStore.currentReservation.pricings as ReservationPricing[]).value

function getPricingQuantity(id: string) {
  return storePricings.find(storePricing => storePricing.id === id)?.quantity || 0
}

// Manage pricing reservation quantity
function increaseReservationPricing(id: string) {
  const currentPricing = storePricings.find(pricing => pricing.id === id)

  if (!currentPricing) return storePricings.push({ id, quantity: 1 })
  currentPricing.quantity += 1
}

function decreaseReservationPricing(id: string) {
  const currentPricing = storePricings.find(pricing => pricing.id === id)

  if (currentPricing && currentPricing.quantity > 0) currentPricing.quantity -= 1
  if (currentPricing?.quantity === 0) reservationStore.cleanPricings()
}
</script>

My store:

import { defineStore } from 'pinia'

// import { postReservation } from '@/api/reservation'
import { ReservationStore } from '../@types/base'
import { ReservationPricing } from '@/@types/base'

const currentReservationInit = {
  clientId: '',
  locationId: '',
  offerId: '',
  day: null,
  hours: {
    opening_hours: null,
    closing_hours: null,
  },
  firstName: '',
  lastName: '',
  email: '',
  phoneNumber: '',
  information: '',
  pricings: [],
  amount: null,
}

export const useReservationStore = defineStore('reservation', {
  state: (): ReservationStore => ({ currentReservation: currentReservationInit }),
  actions: {
    async postReservation() {
      // need to be set
    },
    cleanPricings() {
      const pricings = this.currentReservation.pricings as ReservationPricing[]
      this.currentReservation.pricings = pricings.filter(pricing => pricing.quantity !== 0)
    },
  },
})

Solution

  • It's a mistake to access value immediately, this prevents storePricings from reacting to currentReservation.pricings changes and defies the purpose of a computed.

    It should be:

    const storePricings = computed(() => 
      reservationStore.currentReservation.pricings as ReservationPricing[]
    )
    

    And used like:

    unref(storePricings).find(...)