How to properly get the current state of pinia store to pass as arg for async function

256 views Asked by At

Here I have a simple counter store from pinia. The counter works properly to display the information to the page as it's updated however, the function that I'm using the count in is not getting the updated state of the counter store. How do I properly access this updated state in order to pass it to this wagmi function where the function is actually reading the updated number?

count.ts <-- pinia store

export const useCounterStore = defineStore('counter', {
  state: () => {
    return {
    count: 0
    }
  },
  actions: {
    increment() {
    return this.count++
    },
    decrement() {
      return this.count--
    }
  },
  getters: {
    getCount() {
      return this
    }
  }
});

page.vue

<template>
    <div>
      <button @click="counterStore.increment">+</button>
        <p>{{ counterStore.count }}</p>
          <button @click="counterStore.decrement" :disabled="counterStore.count == 0">-</button>
         <button v-if="user.isConnected" @click="() => write()">Mint</button>
        <p v-else="" @click="user.connect">Connect Wallet</p>
    </div>
</template>

<script setup>
import { useCounterStore } from '#imports'
import { useContractWrite } from 'use-wagmi'
import { parseEther } from 'ethers';
import { useMyUserStore } from '#imports';

const counterStore = useCounterStore()
const user = useMyUserStore()

const { data, isLoading, isSuccess, write } = useContractWrite({
  address: '0x3E966c216fB0b92664DB70b4217AD15d470fe7AC',
    abi: [
  {
      inputs: [
        {
          "internalType": "uint256",
          "name": "amount",
          "type": "uint256"
        }
      ],
      name: "T2GMint",
      outputs: [],
      stateMutability: "payable",
      type: "function"
    }
  ],
  functionName: 'T2GMint',
  value: parseEther('0.015'),
  args: [counterStore.count], //counterStore.count is 0. Using getter function here breaks app
  account: user.address
})

</script>

Using the getter function like const currentCount = counterStore.getCount breaks app. I have read a lot of information about pinia, nuxt and vue and at this point I know I need to somehow be reading the updated state but I'm not sure what the best or easiest way to do it would be. Any help is greatly appreciated.

1

There are 1 answers

0
Darryl Noakes On BEST ANSWER

Stores are reactive objects, so you cannot just destructure them or pass individual properties around while maintaining reactivity.

The solution is to convert the state to an object of refs. With a normal reactive object, you would use Vue's toRefs(); Pinia provides storeToRefs(), which extracts only the state properties from the store, ignoring methods and non-reactive properties.

The docs have an example:

import { storeToRefs } from 'pinia'

const store = useCounterStore()
// `name` and `doubleCount` are reactive refs
// This will also extract refs for properties added by plugins
// but skip any action or non reactive (non ref/reactive) property
const { name, doubleCount } = storeToRefs(store)
// the increment action can just be destructured
const { increment } = store

In your case, you would use it like one of the following (having imported it of course, if needed).

With properties on object:

const counterStore = useCounterStore()
const counterStoreRefs = storeToRefs(counterStore)

// ...

const { data, isLoading, isSuccess, write } = useContractWrite({
  // ...
  args: [counterStoreRefs.count]
  // ...
})

With destructuring:

const counterStore = useCounterStore()
const { count } = storeToRefs(counterStore) // Renaming is supported, of course. E.g., { count: currentCount }

// ...

const { data, isLoading, isSuccess, write } = useContractWrite({
  // ...
  args: [count]
  // ...
})