2

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?

parsecer
  • 4,758
  • 13
  • 71
  • 140

1 Answers1

2

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;
}
Józef Podlecki
  • 10,453
  • 5
  • 24
  • 50
  • What are the props for then? From what I've read of the docs they used props as a place to store router parameters - automatically – parsecer May 29 '20 at 13:55
  • And why did you include `// perhaps you'd like to show loader before data gets fetched` line? Doesn't the data go to the `DisplayAnimal.vue` component right away? I don't make any server requests or anything, just direct the data to the `/viewanimal`. – parsecer May 29 '20 at 13:56
  • Props are for **one-way data transmission**, i.e. from parent to child. If a child needs to modify the parent data, it should emit some kind of event, which the parent has the responsibility of listening and then changing its data. – Terry May 29 '20 at 14:08
  • @Terry But here I don't modify any data - merely display it. Isn't it a one-way transmission? – parsecer May 29 '20 at 14:14
  • 1
    **one-way transmission** refers to the design where parent component passes data to the child. Quite common in Spa frameworks. In this case there is no parent component. Instead you have two separate components which they rely on some routing mechanism/service. Additional thing. Yes, you are modifying data. What's the initial value of `animal` prop before [created](https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram) takes place? probably `undefined/null`. – Józef Podlecki May 29 '20 at 20:12