Props in Vue 3

Props in Vue 3

In the HTML elements, we are having attributes. This attribute provides additional information about elements. Similarly, we are having props as attributes for Components in Vue.js. Props provides additional information about the components. But there is an important difference between HTML elements and Components Props. To clarify, props are reactive and follow one way data flow with its children. Vue.js components require explicit props declaration which it assumes as it’s attributes. Props are declared using the props option,

export default {
  props: ['foo'],
  created() {
    // props are exposed on `this`
    console.log(this.foo)
  }
}

Let’s take a deep dive into that with this post. If you are not familiar with Vue.js components, You should read Components in Vue 3  first.

Props in Vue 3

One way data flow – Props in Vue 3

Props follows one way data flow with it’s child component property. As a result, when we update the value of parent props, it will flow down and update the child property as well. At the same time it will not do vice versa. If you want to update the component state, the flow should start from the parent and all props in the child component will be refreshed with the latest value. We are having event emit concept to reverse back from child to parent in Vue.js.

export default {
  props: ['foo'],
  created() {
    // ❌ warning, props are readonly!
    this.foo = 'bar'
  }
}

Suppose if you want to change the prop in the child component based on business scenario, you can transform the same using computed in Vue.js

export default {
  props: ['size'],
  computed: {
    // computed property that auto-updates when the prop changes
    normalizedSize() {
      return this.size.trim().toLowerCase()
    }
  }
}

Note

However, when passing arrays and objects as props, Vue.js will not prevent mutation of it’s nested properties. Because objects and arrays are passed by reference. Firstly, you should avoid such mutations as a best practice. Secondly, if you need this scenario in-deed, the child can emit an event and the parent listens to it and performs the mutation.

Static and Dynamic Props

The static props are nothing but just assign the static values like below,

<Blog title="I am a static prop example" />

You can also assign dynamic values to props with the help of  v-bind or its : like below

<!-- Dynamically assign the value of a variable -->
<Blog v-bind:title="post.title"></Blog>
// OR
<Blog :title="post.title" </Blog>

Passing other different values to prop

We can pass Numbers, Boolean, Arrays as well as Object to a props value.

// Number
<!-- Even though `42` is static, we need v-bind to tell Vue that -->
<!-- this is a JavaScript expression rather than a string.  -->
<Blog :likes="42" />

<!-- Dynamically assign to the value of a variable. -->
<Blog :likes="post.likes" />

// Boolean
<!-- Including the prop with no value will imply `true`. -->
<Blog is-published />

<!-- this is a JavaScript expression rather than a string. -->
<Blog :is-published="false" />

<!-- Dynamically assign to the value of a variable. -->
<Blog :is-published="post.isPublished" />

// Array
<!-- this is a JavaScript expression rather than a string. -->
<Blog :comment-ids="[234, 266, 273]" />

<!-- Dynamically assign to the value of a variable. -->
<Blog :comment-ids="post.commentIds" />

// Object
<!-- this is a JavaScript expression rather than a string. -->
<Blog
  :author="{
    name: 'Veronica',
    company: 'Veridian Dynamics'
  }"
 />

<!-- Dynamically assign to the value of a variable. -->
<Blog :author="post.author" />

Validation – Props in Vue 3

There are three ways of prop validations available in Vue.js. If the validation fails, then Vue.js will warn us in the browser’s JavaScript console. This is really needed to define the component and the application developers are aware of the intention of the component as well.

  1. Type validation
  2. Mandatory or not (Required)
  3. Custom validator
export default {
  props: {
    // 1. Type Validation
    //  (`null` and `undefined` values will allow any type)
    propA: Number,
    // Multiple possible types
    propB: [String, Number],
    // 2. Mandatory validation with default value
    propC: {
      type: String,
      required: true,
      default: "Hello"
    },
    // 3. Custom validator
    propF: {
      validator(value) {
        // The value must match one of these strings
        return ['success', 'warning', 'danger'].includes(value)
      }
    }
  }
}

In setup Hook – Props in Vue 3

The setup function is the entry point of the Composition API in Vue.js. The first argument of the setup function is the props argument. Props inside the setup function are reactive by nature.

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}

If you destructor the props object, it will lose the reactivity. So we should avoid changing the props object there. But if you really need to destructor the props, you can go for toRefs() and toRef() API.

import { toRefs } from 'vue'

export default {
  setup(props) {
    // turn `props` into an object of refs, then destructure
    const { title } = toRefs(props)
    // `title` is a ref that tracks `props.title`
    console.log(title.value)

    // OR, turn a single property on `props` into a ref
    const title = toRef(props, 'title')
  }
}

Special Feature – Boolean Casting

When we use Boolean props , it has a special casting rule. It is similar to the native Boolean attribute in any programming language. Let me show you with below example,

<!-- equivalent of passing :disabled="true" -->
<MyComponent disabled />

<!-- equivalent of passing :disabled="false" -->
<MyComponent />

// The casting rules for Boolean will apply regardless of type appearance order for below example as well
export default {
  props: {
    disabled: [Boolean, Number]
  }
}

Name Casing in Props

When we declare props in Vue.js we have to follow camelCase. It will avoid to use quotes when we dealing them as property keys, and makes as valid JavaScript identifiers.

export default {
  props: {
    greetingMessage: String
  }
}
// using the “Mustache” syntax (double curly braces)
<span>{{ greetingMessage }}</span>

So when we pass the props values to the child component , we can use camelCase. But Here the convention is kebab-case similar to the one below.

<MyComponent greeting-message="hello" />

Summary

In Conclusion,

  • Firstly, we are having props as attributes for Components in Vue.js. Props provides additional information about the components.
  • Secondly, props follows one way data flow with it’s child component property. When we update the value of parent props, it will flow down and update the child property as well. At the same time it will not vice versa.
  • In Vue.js 3, The first argument of the setup function is the props argument. Props inside the setup function are reactive by nature.

Leave a Reply

%d bloggers like this: