Vue: props doesn't get assigned automatically; when assigned manually - Avoid mutating a prop directly - error

Viewed 71

I have two vue components: GetAnimal.vue and DisplayAnimal.vue. GetAnimal.vue send a JSON with animal data to DisplayAnimal.vue using router push. DisplayAnimal.vue displays that data. It works like this: I go to /getanimal, click a button that triggers the getAnimal() function which leads me to /viewanimal (via a router push):

GetAnimal.vue:

<script>
    import axios from 'axios';

    export default {
        data: function () {
            return {
                name: 'defaultAnimal',
                defaultanimal: {
                    name: 'Cat',
                    furColor: 'red',
                    population: '10000',
                    isExtinct: false,
                    isDomesticated: true
                },
                animal: String
            }
        },
        methods: {
            getAnimal: function () {
                console.log("this.defaultanimal: " +
                    JSON.stringify(this.defaultanimal));

                this.$router.push({
                     name: "viewanimal",
                    params: {
                         animal: this.defaultanimal
                     }
                 });

            },
...

DisplayAnimal.vue:

<template>
    <div>
        <h1>Displaying animal:</h1>
        <p>Animal name: {{animal.name}}}</p>
        <p>Fur color: {{animal.furColor}}</p>
        <p>Population: {{animal.population}}</p>
        <p>Is extinct: {{animal.isExtinct}}</p>
        <p>Is domesticated: {{animal.isDomesticated}}</p>

    </div>
</template>

<script>
    import axios from "axios";

    export default {
        props:  {
            animal:  {
                name: {
                    type: String
                },
                furColor:  {
                    type: String
                },
                population: String,
                isExtinct: String,
                isDomesticated: String
            }
        },

        name: "DisplayAnimal",

        methods: {

        },
        created() {
            console.log("animal param: " +
                JSON.stringify(this.$route.params.animal));
            this.animal = this.$route.params.animal;
        }
    };
</script>

The animal gets displayed just fine:

enter image description here

However I get the warning in console:

enter image description here

The this.animal = this.$route.params.animal; line that assigns the props explicitly is likely the cause of the warning.

However if I remove that line the animal doesn't get displayed at all:

enter image description here

I have this

router.js:

{
    path: "/viewanimal",
    name: "viewanimal",
    component: () => import('./views/DisplayAnimal.vue'),
    props: {animal: true}
},
{
    path: "/getanimal",
    name: "getanimal",
    component: () => import('./views/GetAnimal.vue')
}

I thought setting props: {animal: true} would make sure it's autoassigned, but it doesn't seem to be the case. How should I fix it?

1 Answers

Well updating prop directly is an antipattern

It also doesnt make sense to have animal prop in DisplayAnimal component when you know it is not part of parent component which passes data to it. animal should be inside data so you can update in created callback.

Example

data() {
  return {
    loading: true, // perhaps you'd like to show loader before data gets fetched
    animal: {
        id: -1,
        name: '',
        furColor: '',
        population: 0,
        isExtinct: false,
        isDomesticated: false
    }
  }
},
created() {
  this.animal = this.$route.params.animal;
  this.loading = false;
}
Related