Local component data change Vuex state when it shouldn't

Claudio Ludovico Panetta :

I've a component called EditUser.vue which is linked to a router system using vue router, this is the definition of the route for this component

{
 path: "/users/:id/edit",
 name: "Edit User",
 props: true,
 component: () => import(/* webpackChunkName "edit-user" */ "@/views/EditUser.vue"),
 beforeEnter: (to, from, next) => {
   if (!store.getters.isLogged) next("/");
   else next();
 }
},

Pretty straightforward with props enable because it needs to get the user id.

The component itself is this

<template>
<main class="h-creen p-3">

      <Input
        type="text"
        name="name"
        label="name"
        v-model="user.name"
        required
      />
</main>
</template>

<script>
import { mapState } from "vuex";
import Input from "@/components/Input.vue";

export default {
  name: "EditUserView",

  props: {
    id: {
      required: true,
      type: String,
    }
  },

  components: {
   Input,
  },

  data: () => ({
    user: {},
   }),

  async beforeMount() {
    // TODO move into router file
    if (this.users.length <= 0) {
      this.$router.push("/users");
    }

    this.user = this.users.find(user => user.id == this.id);
  },

  computed: mapState(["users"])
  };
</script>

I've omitted the useless parts, this code replicate the problem anyway. <Input> is just a wrapper for a label and an input with some styling, nothing magic there.

The problems is that if I type something into the input I expect that this.users gets modified, which it happens, but it should not modified the same record inside the Vuex state, but that happens and I don't get why. In other words if I edit the name using the input, this modification gets propagated on the state, thus being rendered in other views, but it shouldn't since it's a local data.

What am I missing here?

Estus Flask :

This results in assigning with a reference to existing object:

this.user = this.users.find(user => user.id == this.id);

When user.name property is changed with v-model two-way binding, the respective nested object is modified in users.

Data should be either shallowly copied to be local (deep copy may be necessary depending on the case):

this.user = {...this.users.find(user => user.id == this.id)};

Then this.user should be copied back to this.users when needed.

Or the component shouldn't have its own user, it can contain separate fields:

  <Input
    type="text"
    name="name"
    label="name"
    v-model="name"
    required
  />

name, etc. can be copied back to this.users when needed.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=293612&siteId=1