Search code examples
vue.jsvuejs2vue-routerroutervue-props

Can we pass data via props when pushing to a route in Vue?


I am asking this question to understand whether we can pass some data via props when navigating the new route. Because I read a few articles which recommend passing data as props and I want to understand if this really works.

As much as I looked into the documentation, passing props in routes works with only two cases-

  1. When you want to use passed params as props.
{ path: '/user/:id', component: User, props: true },
  1. When you want to pass some static data.
{ path: '/user/:id', component: User, props: { value: 123 } },

In both cases, we use the props property in the route's definition.

My question is if we want to pass some data via props when we push to a new route, is it doable? Because I tried this and noticed that passed props are always undefined. There is the same issue on GitHub that stated the problem but I didn't understand their last comment.

Here is the demo which shows that passed props are always undefined in the template.

const Comp1 = Vue.component('Comp1', {
  template: `
  <div>Comp1- <button @click="$router.push({name: 'Comp2',props: { value: 1234 },
      })">Push to route with props</button>
  </div>`,
});

const Comp2 = Vue.component('Comp1', {
  template: `<div>Comp2 - {{ value }} <button @click="$router.push({name: 'Comp1'
      })">Go back</button> </div>`,
  mounted() { console.log('Prop value- ', this.value) },
  props: ['value']
});

const router = new VueRouter({
  routes: [{
      path: '/',
      name: "Comp1",
      component: Comp1,
    },
    {
      path: '/comp1',
      name: "Comp2",
      component: Comp2,
    }
  ]
});

const app = new Vue({
  el: "#app",
  router,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script>
<div id="app">
  <router-view></router-view>
</div>


Solution

  • What is said is that you can't dynamically pass data to a route unless it's in the parameters of the route record or statically provided

    What is a route parameter ?

    A route parameter is a part of the url that should match something, but that is still tied to a given a component. For example, in this route record, :id is a route parameter. It's something that will be dynamic.

    const routes: Route[] = [
      {
        name: 'user-detail',
        path '/users/:id',
        component: UserDetailView,
      },
    ];
    

    Now, the props property in the route record is something used to read differently the parameter in the URL. You can achieve this in 2 ways:

    export default defineComponent({
      props: {
        id: string; // Route params are strings, I'm not sure if you can parse them first
      },
    
      // Composition API
      setup(props) {
        // Method 1
        const route = useRoute();
        const userId = route.params.id;
    
        // Method 2
        const userIdFromProps = props.id
      },
    
      // Options API
      created() {
        // Method 1
        const userId = this.$route.params.id;
    
        // Method 2
        const userIdFromProps = this.id; (this.id reads the prop id)
      },
    });
    

    What's the point of using props then ?

    I may be wrong, but the only use case I see is when you want to use a component as a route's view.

    You have a component that accepts props that you use in another view. And this component matches exactly your requirements, so instead of wrapping it in a view, you directly use it as a route's view, and props are automatically passed down.

    My thoughts

    Given my experience in many apps built with vue, this is something that rarely happens. Params in the route url usually match a ressource's ID, and you usually fetch it before passing it down to a component. So I'd use a wrapper anyway and would never use props on route records.

    The answer:

    After all those explanations I forgot to answer, because the question shouldn't have to be asked:

    You can't pass props when pushing to a new route. The props will be read either from the URL if you use props: true in your route record, or from the route definition (record) if you statically defined it.

    If you want to push data:

    • Either you provide the resource id in the URL to let the page you're pushing to fetching it
    • Either you save it in the localStorage (not recommended, that means your app architecture is maybe not adapted to your needs), and retrieve it on your next page