Home > OS >  Adding new item to an array of a reactive object replaces all items in the array. Why?
Adding new item to an array of a reactive object replaces all items in the array. Why?

Time:07-31

The main problem is in the title. My guess would be that the ref() and reactive() are somehow messing with each other, I just don't know how and what I could do about it.

The component using the store:

<script setup>
    import { ref } from "vue";
    import { store } from "@/store.js";

    const game = ref({
        date: null,
        location: null,
        length: null,
    });
</script>

<template>
    <form @submit.prevent="store.addGame(game)">
        <input v-model="game.date" type="date" required />
        <input v-model="game.location" type="text" placeholder="Location" required />
        <input v-model="game.length" type="number" placeholder="Length (in minutes)" required />
        <button  type="submit">Submit ✔</button>
    </form>
</template>

The problem occurs in the store, in the games array, after I add a second or more items...

store.js:

import { reactive } from "vue";

export const store = reactive({
    games: [],

    addGame(game) {
        this.games.push(game);
        console.log(this.games);
    }
});

CodePudding user response:

The reason is because all the objects that you push inside games share the same reference. To fix this, do this change in store.js

import { reactive } from "vue";

export const store = reactive({
    games: [],

    addGame(game) {
        this.games.push({...game}); // line changed
        console.log(this.games);
    }
});

CodePudding user response:

It's not "replace", all the game reference to the same reactive variable defined in const game = ref().

Whenever you call store.addGame(game), you added the same game to the store. Because the game is reactive, is will automatic implement the latest input value by v-model.

If you put another button to check the value in store. Change the input value, and then click Test button, you can see the store.games changes too.

<template>
    <form @submit.prevent="store.addGame(game)">
        <input v-model="game.date" type="date" required />
        <input v-model="game.location" type="text" placeholder="Location" required />
        <input v-model="game.length" type="number" placeholder="Length (in minutes)" required />
        <button  type="submit">Submit ✔</button>
    </form>
    <button @click="console.log(store.games)">Test</button>
</template>
  • Related