web-dev-qa-db-fra.com

Mise à jour de l'état du tableau vuex lorsqu'un élément comporte des modifications

J'ai un tableau appelé cases dans mon magasin vuex.

Je souhaite mettre à jour le tableau avec le nouveau contenu lorsque je mets à jour quelques champs d'un élément existant dans le tableau.

Je pensais que je pouvais faire quelque chose comme ça dans ma mutation mais ne fonctionne pas et obtenir l'erreur typeError: undefined is not an object (evaluating 'state.objects.find') -

EDIT_CASE (state, payload) {
    const item = state.objects.find(item => item.id === payload.recordId);
Object.assign(item, payload.case_status);

mon tableau est le suivant:

[
    {
        "case_name": "Laptop not working",
        "case_status": "live",
        "case_summary": "This is some summary content",
        "createdBy": "zippy",
        "createdDate": "2018-06-21T15:20:22.932Z",
        "id": "-LFXvk9yY5c-O8yIdf8k"
    },
    {
        "case_name": "Something else",
        "case_status": "live",
        "case_summary": "This is some summary content",
        "createdBy": "zippy",
        "createdDate": "2018-06-21T15:20:22.932Z",
        "id": "-STVvk9yY5c-O3yiTy8k"
    }
]

Je pense également que d'après ce que j'ai lu Vue n'observe pas les changements dans les tableaux, il se peut donc que je fasse complètement le mauvais chemin avec cela, et que je dois supprimer puis rajouter le tableau article?

Fondamentalement, j'ai une liste, je modifie mon backend, maintenant je veux que cette liste reflète les changements que j'ai apportés en mettant à jour l'état des cas, quelqu'un peut-il m'aider?

11
Paul

Il n'y a pas de problème de tableau avec votre exemple car vous essayez de changer une propriété d'objet - pas une référence d'élément de tableau . Le problème est dans Object.assign(item, payload.case_status); - vous devez fournir un objet et pas seulement un champ. (Vous avez également dit que le tableau s'appelait cases mais l'exemple a objects, c'est peut-être aussi un problème);

Cela devrait donc fonctionner:

EDIT_CASE (state, payload) {
    const item = state.objects.find(item => item.id === payload.recordId);
    Object.assign(item, payload);
}

L'erreur:

undefined n'est pas un objet

Je pense que c'est lié à Object.assign parce que vous lui passez un champ qui est non défini probablement.

P.S. Il y a un petit exemple pour vous aider à comprendre quand le problème de tableau apparaît et quand tout fonctionne bien. Voir les commentaires de code :)

new Vue({
  el: "#app",
  data: {
    todos: [
      { text: "Learn JavaScript" },
      { text: "Learn Vue" },
      { text: "Play around in JSFiddle" },
      { text: "Build something awesome" }
    ]
  },
  methods: {
    // work because object property is reactive
        changeItemProperty() {
        this.todos[3].text = "changedItemProperty";
    },
    // same reason, properties are reactive
    changeItemWithAssign() {
        Object.assign(this.todos[3], { text: "changedItemWithAssign" });
    },
    // does not work, can not track changes in array
    // also this will break all attempts to change TEXT property in UI
    // because property becomes not reactive after this due to new object
    // try to changeItemProperty or  changeItemWithAssign - does not work!
    // changeItem2 will fix it :)
    changeItem() {
        this.todos[3] = { text: "changedItem" }
    },
    // works
    changeItem2() {
        Vue.set(this.todos, 3, { text: "changedItem2" });
    }   
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
  <div v-for="todo in todos" :key="todo.text">
     {{todo.text}}
  </div>
  <button @click="changeItemProperty">changeItemProperty(works)</button>
  <button @click="changeItemWithAssign">changeItemWithAssign(works)</button>
  <button @click="changeItem">changeItem(does not work!)</button>
  <button @click="changeItem2">changeItem2(works)</button>
</div>
19
Max Sinev

JavaScript (non spécifique à Vue) ne peut pas détecter la définition de la valeur d'un élément de tableau directement par l'index arr[3] = 'stop'; Il ne peut pas non plus détecter ajout une nouvelle clé ou suppression une clé existante d'un objet. Vous devez définir l'état initial du magasin, par exemple.

const store = new Vuex.Store({
  state: {
    objects: []
  },
  mutations: {
    EDIT_CASE (state, payload) {
      const index = state.objects.findIndex(item => item.id === payload.id);
      if (index !== -1) state.objects.splice(index, 1, payload);
    }
  }
})
6
IVO GELOV

vous devez mettre à jour votre baie

const store = new Vuex.Store({
  state: {
    objects: [
      {id: 1, someProps: 'blablabla'},
      {id: 2, someProps: 'ololololo'}
   ]
  },
  mutations: {
    EDIT_CASE (state, data) {
      const index = state.objects.findIndex(item => item.id === data.id);
      state.objects[index].someProps = data.newPropsValue;

      //this is for vue reaction
      state.objects.Push('dog-nail');
      state.objects.splice(-1,1);
  }
})
1
Paul