Home > OS >  how can I update a vue child-component from the vuex-store
how can I update a vue child-component from the vuex-store

Time:11-14

My application shows a window where player can enter name and passcode to enter

When the player exists and has a card, I want to show the card as well. When the player exists, I make the card visible. Then in 'created'I call fetchSpelerCards. This is successful but shows in the VUE console as pending...

I hope some experienced vue user reads this and can help me with a hint, reference or explanation.

For that I have in the following code:

 <h2>Meld je aan</h2>
    <form @submit.prevent="register" > 
        
        <div >
            <input type="text"  placeholder="naam" v-model="name">
        </div>

        <div >
            <input type="text"  placeholder="kies inlogcode" v-model="pass_code">     
        </div>

        <button type="submit" @click="checkSpeler()"   style="color:white">Save</button>
    </form>
    <p  v-if="errorMessage !== ''"> {{errorMessage}} </p>
    <p  v-if="successMessage !== ''"> {{successMessage}} </p>
    <CardsSpeler v-if="spelerCorrect"></CardsSpeler>
    
</div>
</template>

The component looks as follows:

 <h2>Cards 1</h2>
    <form @submit.prevent="addCard" > 
        <div >
            <input type="text"  placeholder="title" v-model="card.title">
        </div>

        <div >
            <textarea   placeholder="description" v-model="card.description">
            </textarea>
        </div>

        <div>
            <input type="file" v-on:change="onFileChange" ref="fileUpload" id="file_picture_input">
        </div>

        <button type="submit"  style="color:white">Save</button>
    </form>
    <div  v-for="card in cards" v-bind:key="card.id">   
        <h3> {{currentSpelerCard.title}}   </h3>
        <p> {{currentSpelerCard.description}}</p>
        <img  style="width:150px" v-bind:src="currentSpelerCard.picture" alt="Card Image">


    </div>
</div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
    mounted(){
        console.log('component mounted');  
    },
    computed: {
        ...mapState([
        'currentSpeler' ,'currentSpelerCard'
        ]), 
    },
    data() {
        return{
            cardExists:false,
            successMessage:'',
            errorMessage:'',
        }

    },
    created(){
      this.fetchSpelerCards();
    },
    methods: {

        ...mapActions([  'getGames', 'addGame', 'fetchSpelerCards'  ]),

        fetchSpelerCards(){
            
                this.$store.dispatch('fetchSpelerCards', this.currentSpeler.speler.id )
                .then(res => { 
                    this.cardExists = true;
                    this.successMessage = res;
                    console.log(res);
                })
                .catch(err => {
                    this.errorMessage = err;
                    this.cardExists = false;
                });
            
        },

The corresponding action, in actions.js is:

export const fetchSpelerCards = ({commit}, speler_id) => {
    return new Promise((resolve, reject) => {     
        let status = '';
        let data ={};
        fetch(`api/cardsBySpeler/${speler_id}`)
        .then(res => {
            status = res.status;
            data = res.json(); 
        })
        .then(res=>{
            if ( status === 200) {
                commit('SET_PLAYER_CARD', data);
                resolve('Kaart gevonden');
            }
            else {
                reject('Er is geen kaart beschikbaar')
            }
        });
    })
}

In the vuex-store I see (viewed with VUE add-on of chrome browser):

currentSpelerCard: Promise

Yet, the response of the fetch command was successful, and the card was pulled in, as I see also in the console: status 200, I can see name, title, image address etc..

I was under the assumption that, when the promise eventually resolves, the store is updated and the card becomes available because of the:

computed: {  ...mapState([  'currentSpeler' ,'currentSpelerCard' ]),

Can anyone help me and explain what I am doing wrong?

CodePudding user response:

Try to rename your method, and wait to finish:

async mounted(){
  await this.initSpelerCards();
},
methods: {
  ...mapActions([ 'getGames', 'addGame', 'fetchSpelerCards' ]),

  initSpelerCards(){
    this.fetchSpelerCards(this.currentSpeler.speler.id)
      .then(res => { 
        this.cardExists = true;
        this.successMessage = res;
        console.log(res);
      })
      .catch(err => {
        this.errorMessage = err;
        this.cardExists = false;
      });
  },
}

CodePudding user response:

fetchSpelerCards in Vuex commits SET_PLAYER_CARD with data, this will be a pending promise. You need to await the promise.

You can solve this in a few different ways.

Making the function async and await res.json() would be the easiest.

...
  fetch(`api/cardsBySpeler/${speler_id}`)
    .then(async res => {
      status = res.status;
      data = await res.json(); 
    })
...
  • Related