A. L
A. L

Reputation: 12669

Vue computed property not updating with updated props

I'm not sure why my props aren't updating when I update the data in my parent component. I've tried it out in a fiddle and it works https://jsfiddle.net/f3w69rr6/1/ but it doesn't work in my app.

parent:

methods: {
    addToHand(index) {
        let card = this.gameState.playerDeck.splice(index, 1)
        if (this.gameState.playerHand.length < 12)
        {
            // put card into hand
            this.$set(this.gameState, 'playerHand', [...this.gameState.playerHand, card])
            // this.gameState.playerHand.push(card)
        }
        // otherwise discard card
    },
    retrieveDeck() {
        let array = []
        for (let i = 0; i < 20; i++)
        {
            array.push(this.src + "?text=card"+i)
        }
        this.$set(this.gameState, 'playerDeck', array)
    },
},
mounted () {
    this.retrieveDeck()
    for (let i = 0; i < 5; i++)
    {
        this.addToHand(1)
    }
},

putting the data into child via:

<PlayerCards :gameState="gameState" :hand="gameState.playerHand" />

child:

export default {
    name: 'PlayerCards',
    props: ["gameState", "hand"],
    data() {
        return {
        }
    },
    computed: {
        rows() {
            let cards = this.gameState.playerHand
            let max = 6;
            if (cards.length <= max)
                return [cards]

            var mid = Math.ceil(cards.length / 2);
            let return_value = [cards.slice(0, mid), cards.slice(mid)]
            return return_value
        }
    }
}

but the row content is empty.

Update (Updated fiddle):

The problem is with the compute

https://jsfiddle.net/f3w69rr6/1/

Upvotes: 1

Views: 4172

Answers (3)

craig_h
craig_h

Reputation: 32724

If you're not using string templates then you need to use the kebab-case equivalent to your camelCase prop:

<PlayerCards :game-state="gameState" :hand="gameState.playerHand" />

The reason it works in your fiddle is because you are using a string template (see: https://v2.vuejs.org/v2/guide/components.html#camelCase-vs-kebab-case)

Upvotes: 2

A. L
A. L

Reputation: 12669

I believe this was due to a misuse of the computed property. Switching it over to data and using this.$set updates as expected. If I were to use computed then setters would be needed. Computed also seems to be more suited for combining/updating data properties rather than being a property in and of itself.

Upvotes: 0

funnyecho
funnyecho

Reputation: 11

Look at your demo in jsfiddle:

rows() {
    let cards = this.gameState.playerHand
    let max = 6;
    if (cards.length <= max)
      return [cards]

    var mid = Math.ceil(cards.length / 2);
    let return_value = [cards.slice(0, mid), cards.slice(mid)]
    return return_value      
  }

Actually, vue has notified the computed function successfully when gameState.playerHand has updated. But you wrapped the computed property: rows into an array, like: [cards] and [cards.slice(0, mid), cards.slice(mid)]. And obviously, the rows.length will be 1 or 2.

Upvotes: 0

Related Questions