How to pass reactive data to Vue components using pinia store elements?

Viewed 36
  • GamePage.vue

Destructured the pinia state elements and action method

const $store = useGameStore();
const {game, teamOne, teamTwo} = storeToRefs($store);
const { getGame } = $store;

Passed the destructed variables to components

<player-stat-table
  :title="teamTwo.name"
  :players="teamTwo.players"
  :teamColor="teamTwo.team_color"
 />
  • Table Display

table

  • store/game_store.js

I am trying to edit data from the above table using updatePlayer action, after successfully completing the action I am updating the entire store data by recalling the get action method. But the data in the table is not updating reactively, it's updating after page reload. How to update it reactively?

import { api } from 'boot/axios'
import { defineStore } from 'pinia'

import { splitPlayers } from 'src/helpers'

export const useGameStore = defineStore('game', {
  state: () => ({
    game: null,
    teamOne: null,
    teamTwo: null,
  }),

  getters: {
    getTeamOne: state => state.teamOne,
    getTeamTwo: state => state.teamTwo,
    getGameData: state => state.game,
  },

  actions: {
    getGame(payload) {
      return new Promise((resolve, reject) => {
        api.get(`/games/${payload.gameID}/`)
        .then(resp => {
          const data = resp.data;
          const teams = splitPlayers(data)
          this.game = data
          this.teamOne = teams[0]
          this.teamTwo = teams[1]
          resolve(data)
        })
      })
    },
    updatePlayer(payload) {
      return new Promise((resolve, reject) => {
        api.put(`/playerstat/${payload.id}/`, data)
        .then(resp => {
          const data = resp.data;
          this.getGame({gameID: data.game})
          resolve(data)
        })
      })
    },
  }
})
1 Answers

First, you can get rid of you getters, cause due to pinia documentation,

as getters you can think of as the computed properties

and you're not computing anything. So you can simply access the state properties, what you are already doing in your GamePage.vue file.

Secondly, you should also consider async/await pattern instead of Promiste.then(). Like mentioned in the comments, there's a problem with promise constructor antipattern in the OP.

I also prefer writing my pinia stores with the setup() approach, because I think it fits the vue3/composition-api approach a bit better.

import { api } from 'boot/axios'
import { defineStore } from 'pinia'
import { splitPlayers } from 'src/helpers'

export const useGameStore = defineStore('game', () => {
  
  const game = ref(null);
  const teamOne = ref(null);
  const teamTwo = ref(null);

  const getGame = async (gameId) => {
    const resp = await api.get(`/games/${gameId}/`);
    const teams = splitPlayers(resp.data)
    game.value = resp.data
    teamOne.value = teams[0]
    teamTwo.value = teams[1]
  };

  const updatePlayer = async (data) => {
    const resp = await api.put(`/playerstat/${data.id}/`, data)
    const gameId = resp.data.game;
    await getGame(gameId)
  };
  
  return {
    game,
    teamOne,
    teamTwo,
    getGame,
    updatePlayer
  }
});

Related