Passing data down through component props is a common Vue pattern. How do we validate props & what are some best-practices when using them? 🧐
In this tutorial, we will cover best-practices props validation and things to watch out for when passing data down from one component to another.
Let's have a look at the bigger picture first and then dig deeper. 😎
A long list of props with all sort of validation criteria:
props: {
// Basic type check (`null` and `undefined` values will pass any type validation)
luckyNumber: Number,
// Multiple possible types
flexibleProp: [String, Number],
// Required string
name: {
type: String,
required: true
},
// Number with a default value
percentage: {
type: Number,
default: 100
},
// Object with a default value
profile: {
type: Object,
// Object or array defaults must be returned from
// a factory function
default: function() {
return { name: "Mr. 007", email: "james@bond.io" };
}
},
// Custom validator function
season: {
validator: function(value) {
// The value must match one of these strings
return ["winter", "summer", "autumn", "spring"].includes(value);
}
},
// Array with a type-check validator function.
skills: {
type: Array,
validator: prop => prop.every(e => typeof e === "string")
},
// Imported custom validator function
phoneNumber: {
validator: prop => phoneNumberValidator(prop)
}
}
Let's explore the different use-cases applied here...
A simple example of how we can add a number type to a prop:
props: {
luckyNumber: Number,
}
Did you notice the prop's name was a camel-cased?
Vue Automatically translates any camel-cased prop into kebab-case when used in a template.
Here is how you would pass the data in the previous example of luckyNumber:
<!-- parent component -->
<game-of-life :lucky-number="7"></game-of-life>
And here is how you would use the prop in the child component's template
<!-- child component -->
<template>
<h1>{{ luckyNumber }}</h1>
</template>
Now, let's cover some of the basic validation types...
Out of the box, Vue allows these native types:
So you can do things like this...
<script>
export default {
props: {
name: String,
luckyNumber: Number,
isLucky: Boolean,
luckyPlaces: Array,
luck: Object,
birthday: Date,
luckCallback: Function,
friendsPromise: Promise // or any other custom constructor
}
};
</script>
In addition, you can create your own custom constructors!
I don't use often that validation pattern myself but it definitely can be handy in certain use-cases.
Here is a simple demonstration:
<script>
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
export default {
props: {
author: Person
}
};
</script>
You may have also noticed earlier that there were some validator functions used in the props list. Let's have a closer look at these...
The validator property allows you to create your own custom validator function.
They are very handy for example when validating items of an array or object's values.
props: {
// Custom validator function
season: {
validator: function (value) {
// The value must match one of these strings
return ['winter', 'summer', 'autumn', 'spring'].includes(value)
}
},
// Array with a type-check validator function.
skills: {
type: Array,
validator: (prop) => prop.every(e => typeof e === 'string'),
}
}
You can also have shared custom validation functions that you import to different components, here is an example of of a phone number validator...
props: {
// Imported custom validator function
phoneNumber: {
validator: prop => phoneNumberValidator(prop);
}
}
// Phone Number Validator Fn
export function phoneNumberValidator(data) {
const phoneNumberRegex = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im;
return data.match(phoneNumberRegex);
}
Vue allows you to define a default value for a prop.
// The user may not provide a value, so we should just in case
props: {
// Object with a default value
profile: {
type: Object,
// Object or array defaults must be returned from
// a factory function
default: function () {
return { name: 'Mr. 007', email: 'james@bond.io' }
}
},
birthday: {
type: Date,
default: new Date('July 10, 1856'), // forever young
}
}
Note, for objects & arrays the default values must be returned through a function as you can see above.
If you happen to pass the wrong type to a prop, you should see in the console something similar to this...
Now you should know your way around props validations, time for some best-practices...
Here are some guidelines I follow myself:
That is it, now you can validate your props like a pro! 🔥
Enjoyed the article? Share the summary thread on twitter.