Reputation: 4905
when I update a value in an array of the store, the interface doesn't reflect the change.
Goal: I'm trying to display a simple minesweeper grid. Once I click on a cell, the object attach to that cell should update isRevealed to true to say is was revealed and Vuejs should add the class dug to that cell.
What's working: isRevealed is switched to true.
What was working: using only props everything was working, but trying to learn VueJS and including Vuex store the UI doesn't update anymore with the array.
Structure:
App shows a grid and grid shows multiple cell.
store.js for Vuex
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
GameGrid: [],
},
mutations: {
revealCell(state, cell) {
state.GameGrid[cell.y][cell.x].isRevealed = true;
console.log("revealCell ", cell);
},
});
GameGrid contain the following: 10 arrays of 10 objects:
{
isRevealed: false,
x: 0,
y: 0
...
}
grid.vue, nothing special, display every cell
<template>
<div class="grid">
<div v-for="row in $store.state.GameGrid" class="row">
<app-cell v-for="col in row" :cell="col"></app-cell>
</div>
</div>
</template>
cell.vue:
<template>
<div
@click="dig"
:class="{dug: cell.isRevealed, dd: cell.debug}">
<span class="text" v-html="cell.display"></span>
<span class="small">{{ cell.code }}</span>
</div>
</template>
<script>
export default {
props: {
cell: {
type: Object
},
},
data: function() {
return {
display: null,
}
},
methods: {
dig() {
this.$store.commit('revealCell', this.cell);
},
}
</script>
Grid.vue file
<template>
<div class="grid">
<div v-for="row in gameGridAlias" class="row">
<app-cell v-for="col in row" :cell="col"></app-cell>
</div>
</div>
</template>
<script>
import { mapState } from 'vuex';
import Cell from './Cell.vue';
export default {
components: {
'app-cell': Cell,
},
data: {
gameGridAlias: []
},
methods: {
},
computed: mapState({
gameGridAlias: state => state.GameGrid
})
}
</script>
Note that I get The "data" option should be a function that returns a per-instance value in component definitions.
error since data
doesn't return a function.
My functions to set isRevealed are on the cell.vue though. I'm still seeing no UI updates (except when I'm saving?). Cells with this.cell.isRevealed = true
confirmed with console.log but no change in classes.
This function is calling when the user press a button on the hmm, home page? App.vue file.
generateGrid() {
console.log("generateGrid");
//Generate empty play grid
for(let y = 0; y < this.$store.state.GameGridHeight; y++) {
this.$store.state.GameGrid[y] = new Array();
for(let x = 0; x < this.$store.state.GameGridWidth; x++) {
this.$store.state.GameGrid[y][x] = {
content: 'Empty',
code: 0,
isRevealed: false,
x: x,
y: y,
debug: false,
};
}
}
}, //End generateGrid
Upvotes: 2
Views: 2310
Reputation: 2260
state.GameGrid[cell.y][cell.x].isRevealed = true;
add this
state.GameGrid = Array.from(state.GameGrid); //force reflection by cloning array
It is not the most efficient solution but it only one that works for me
Upvotes: 0
Reputation: 2463
In your grid.vue
, you should use computed
and mapState
to update the props
It would be like:
import { mapState } from 'vuex'
// ...
<div v-for="row in gameGridAlias" class="row">
// ...
computed: mapState({
gameGridAlias: state => state.GameGrid
})
More : https://vuex.vuejs.org/en/state.html#the-mapstate-helper
*Note: mapState
is optional, but you can handle multiple stores with it and it's robust, i use it for all cases personally.
Edit: Don't use this.$store.state.GameGrid[y]
or another this.$store.state
vars but only mapState
aliases to make it work correctly
Upvotes: 2