Editor’s note: This article was last updated 15 December 2022 to reflect updates made in Vue 3.
Props are an important feature in Vue for managing parent and child components, but handling them can be somewhat tricky. In this article, we’ll learn how to pass data from a parent component to child components by using props in Vue 3. You can find the complete code for this tutorial on GitHub. Let’s get started!
Table of contents
- Prerequisites
- What are props in Vue?
- Why should you use props?
- Defining data in the parent component
- Receiving props in Vue
- Registering props in Vue
- Using props in Vue
- Strongly typing props
Prerequisites
This article is suited for developers of all stages, including beginners.
To follow along with this article, you’ll need Node.js version ≥16.x installed. You can verify if you already have it installed by running the command below in your terminal or the command prompt:
node -v
You’ll also need a code editor; I highly recommend VS Code. Finally, you’ll need Vue 3 installed globally on your machine. At the time of writing, Vue3 is the latest version.
Before getting started, go ahead and download a Vue starter project. Unzip the downloaded project, navigate into the unzipped file, and then run the command below to keep all the dependencies up-to-date:
npm install
What are props in Vue?
In Vue, props are custom attributes that you can register on any component. You define your data on the parent component and give it a value. Then, you go to the child component that needs that data and pass the value to a prop attribute. Therefore, the data becomes a property in the child component.
In a <script setup>
component, the syntax looks like the following code:
<script setup> const props = defineProps(['title']) console.log(props.title) </script>
In a non-<script setup>
component, the syntax looks like the following:
export default { props: ['title'], setup(props) { // setup() receives props as the first argument. console.log(props.title) } }
To access this data dynamically from any component that needs it, you can use the root component App.vue
as the parent component, store the data, and then register props.
Why should you use props in Vue?
Let’s say you have a data object that you want to display in two different components but in very different ways, for example, the Billboard Top 10 Artists list. Your first instinct might be to create these two separate components, add the array inside the data object, and then display them in the template.
This solution is great initially, but as you add more components, it stops being efficient. Let’s demonstrate this with the starter project you’ve opened in VS Code. Open the Test.vue
file and copy the code block below:
<template> <div> <h1>Vue Top 20 Artists</h1> <ul> <li v-for="(artist, x) in artists" :key="x"> <h3>{{artist.name}}</h3> </li> </ul> </div> </template> <script> export default { name: 'Test', data (){ return { artists: [ {name: 'Davido', genre: 'afrobeats', country: 'Nigeria'}, {name: 'Burna Boy', genre: 'afrobeats', country: 'Nigeria'}, {name: 'AKA', genre: 'hiphop', country: 'South-Africa'}, {name: 'Sarkodie', genre: 'hiphop', country: 'Ghana'}, {name: 'Stormzy', genre: 'hiphop', country: 'United Kingdom'}, {name: 'Lil Nas', genre: 'Country', country: 'United States'}, {name: 'Nasty C', genre: 'hiphop', country: 'South-Africa'}, {name: 'Shatta-walle', genre: 'Reagae', country: 'Ghana'}, {name: 'Khalid', genre: 'pop', country: 'United States'}, {name: 'ed-Sheeran', genre: 'pop', country: 'United Kingdom'} ] } } } </script>
Create a new file in the components folder called Test2.vue
and paste the following code block inside it:
<template> <div> <h1>Vue Top Artist Countries</h1> <ul> <li v-for="(artist, x) in artists" :key="x"> <h3>{{artist.name}} from {{artist.country}}</h3> </li> </ul> </div> </template> <script> export default { name: 'Test2', data (){ return { artists: [ {name: 'Davido', genre: 'afrobeats', country: 'Nigeria'}, {name: 'Burna Boy', genre: 'afrobeats', country: 'Nigeria'}, {name: 'AKA', genre: 'hiphop', country: 'South-Africa'}, {name: 'Sarkodie', genre: 'hiphop', country: 'Ghana'}, {name: 'Stormzy', genre: 'hiphop', country: 'United Kingdom'}, {name: 'Lil Nas', genre: 'Country', country: 'United States'}, {name: 'Nasty C', genre: 'hiphop', country: 'South-Africa'}, {name: 'Shatta-walle', genre: 'Reagae', country: 'Ghana'}, {name: 'Khalid', genre: 'pop', country: 'United States'}, {name: 'ed-Sheeran', genre: 'pop', country: 'United Kingdom'} ] } } } </script> <style scoped> li{ height: 40px; width: 100%; padding: 15px; border: 1px solid saddlebrown; display: flex; justify-content: center; align-items: center; } a { color: #42b983; } </style>
To register the new component you just created, open the App.vue
file and copy the code below inside it:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <Test/> <Test2/> </div> </template> <script> import Test from './components/Test.vue' import Test2 from './components/Test2.vue' export default { name: 'app', components: { Test, Test2 } } </script>
In the VS Code terminal, serve up the application in the development environment with the following command:
npm run dev
It should look like the following:
You’ll notice that if you had only about five more components, you would have to keep copying the data in every component. Imagine there was a way that you could define the data in a parent component and then bring it into every child component that needs it by using the property name.
Defining data in the parent component
Since you’ve chosen the root component to be your parent component, you first have to define the data object that you want to share dynamically inside of the root component. If you’ve followed this article from the start, open up your App.vue
file and copy the data object code block inside of the script section:
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png" /> <Test /> <Test2 /> </div> </template> <script> import Test from "./components/Test.vue"; import Test2 from "./components/Test2.vue"; export default { name: "app", components: { Test, Test2, }, data() { return { artists: [ { name: "Davido", genre: "afrobeats", country: "Nigeria" }, { name: "Burna Boy", genre: "afrobeats", country: "Nigeria" }, { name: "AKA", genre: "hiphop", country: "South-Africa" }, { name: "Sarkodie", genre: "hiphop", country: "Ghana" }, { name: "Stormzy", genre: "hiphop", country: "United Kingdom" }, { name: "Lil Nas", genre: "Country", country: "United States" }, { name: "Nasty C", genre: "hiphop", country: "South-Africa" }, { name: "Shatta-walle", genre: "Reagae", country: "Ghana" }, { name: "Khalid", genre: "pop", country: "United States" }, { name: "Ed Sheeran", genre: "pop", country: "United Kingdom" }, ], }; }, }; </script>
Receiving props in Vue
After defining the data, go into the two test components and delete the data objects inside them. To receive props in a component, you have to specify the props that you want to receive inside of that component. Go inside the two test components and add the specifications in the script section, as shown below:
<script> export default { name: 'Test', props: ['artists'] } </script>
Registering props in Vue
To let the Vue engine know that you have props you want to dynamically pass to some child components, you have to indicate it in the Vue instance. This is done in the template section as follows:
<template> <div id="app"> <Test v-bind:artists="artists"/> <Test2 v-bind:artists="artists" /> </div> </template>
In the code above, we use the v-bind
directive to bind artists
, which is the name of the data object array in the script section, and artists
, the prop name in the test components, which you set up in the section above.
If you set it up without the following directive, you won’t see any output; the Vue compiler and even ESLint won’t flag it as an error or warning:
<Test artists="artists"/> <Test2 artists="artists"/>
Therefore, it’s important to pay attention and remember to use v-bind
for every dynamic binding.
Using props in Vue
After you’ve set up the props in your Vue app, you can then use them inside of your component as if the data was defined inside of the same component. Therefore, you can set up method calls and easily access this.artists
in our demo case.
Strongly typing props
By strongly typing the props, you can also ensure that your component only receives exactly the data type you want it to. In our demo, for instance, you can ensure that only arrays get passed down to your component by setting up authentication as follows:
<script> export default { name: 'Test', props: { artists: { type: Array } } } </script>
Therefore, whenever you add a wrong type, say, a String
, you’ll get a warning in the console telling you that the type it received is not the type it expected:
Conclusion
In this article, we explored props in Vue 3, learning how they can help to encourage the DRY (don’t repeat yourself) approach by creating a platform for reusing data objects. We’ve also learned how to set up props in your Vue project. For additional information, check out Vue’s official documentation on props. Happy coding!
Experience your Vue apps exactly how a user does
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps - Start monitoring for free.
Hey Nwose! Thanks so much for the awesome explanation. I was struggling a bit with it, but you made it much more clear. <3
Thank you brother for this awesome tutrials
Nwose, excelent explanation, very clear and easy to learn… thanks !
Thank you Nwose! Vue is a little bit overwhelming in the beginning, your well structured tutorial helped me understand the concept of sending data between components.
Thanks so much – was looking for something as clear and good as this for hours !1
Straightup to the koko… Nice one
The way you explained clearly with examples was brilliant!