Passing data from Parent Component to Child Component in Vue.js

Properties, commonly known as props, are a key mechanism that allow data to be passed from a parent component to a child component. They provide a way to make components more modular and reusable

October 24, 20246 min read

Vue.js is one of the most loved frontend frameworks in the Javascript ecosystem, it is particularly popular because of its ease of use when creating user interfaces. Amongst its crazy pool of awesome features is how it lets you pass data from the parent to the child component with ease. We are going to look at some of the ways of making this possible smoothly using props.

Understanding Vue Components

Components are the building blocks of any Vue application. They encapsulate HTML, CSS, and JavaScript, making it easy to manage and reuse UI in your application. In Vue and other component-based frameworks, a parent component is the component that contains or uses another component. The parent component is responsible for rendering the component it contains, which is referred to as the child component. Apart from rendering the child component, the parent component is also responsible for passing data to the child component through props.

Understanding props

Properties, commonly known as props, are a key mechanism that allow data to be passed from a parent component to a child component. They provide a way to make components more modular and reusable by allowing data to be passed into the child components allowing flexibility in the child component based on the data is receives from the parent. Props work in a similar manner for most frameworks like React, just to give an analogy props are like funnels, you use a funnel to transfer contents between containers, in this case the contents are the data and props are the funnels. They basically allow the parent and the child components to communicate.

Try Kodaschool for free

Click below to sign up and get access to free web, android and iOs challenges.

Sign Up

Static vs Dynamic Props

Props are very important in passing data from parent to child components, but not all props are the same, depending on what we're trying to achieve, we can choose between static and dynamic props to make component communication even better and build stronger applications.

Static props

This refer to props passed from parent to child components and their values do not change through out the application life cycle, when you pass a static prop it behaves like a constant, the values remain same, they are technically hardcoded values and are not dynamically bound to any data in the parent component.

Example parent component


<template>
  <ChildComponent message="Hello from Parent!" age="30" />
</template>

In the example above:

The message prop is passed with the static string value "Hello from Parent!" .The age prop is passed with the static value 30.These values are static because they are hardcoded in the template and not bound to any reactive data or expressions in the parent component.

Example Child Component

<template>
  <div>
    <p>{{ message }}</p>
    <p>Age: {{ age }}</p>
  </div>
</template>

<script>
export default {
  props: {
    message: String,
    age: Number,
  },
};
</script>

In this case, the child component receives the static message and age props from the parent and renders them accordingly.

Dynamic props

Dynamic props are props whose values can change depending on user interaction, application state or other elements, their values are commonly bound to variables or expressions in the parent component.

Example parent component

<template>
  <div>
    <input v-model="userMessage" placeholder="Enter a message" />
    <ChildComponent :message="userMessage" :age="userAge" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  data() {
    return {
      userMessage: "Hello, Vue!",  // Bound to input
      userAge: 25                 // Static for now, could be dynamic
    };
  },
  components: {
    ChildComponent
  }
};
</script>

Example Child Component

<template>
  <div>
    <p>Message: {{ message }}</p>
    <p>Age: {{ age }}</p>
  </div>
</template>

<script>
export default {
  props: {
    message: String,
    age: Number
  }
}
</script>

Passing Different Value Types as Props in Vue

We have seen how easy it is to pass value types from parent to child component, a side from the usual datatypes, number, strings and Booleans, Vue lets you pass different value types like the arrays and the objects. It even lets you pass functions.

Passing arrays

// ParentComponent
<ChildComponent :numbers="[1, 2, 3]" />

// ChildComponent.vue
<script>
export default {
  props: {
    numbers: Array,
  },
};
</script>

Passing Objects

// ParentComponent
<ChildComponent :author="{ name: 'John', age: 18 }" />

// ChildComponent.vue
<script>
export default {
  props: {
    author: Object,
  },
};
</script>

Passing Functions

// In ChildComponent.vue
<ChildComponent :prop-fn="() => { /* do something */ }" />

// ChildComponent.vue
<script>
export default {
  props: {
    propFn: Function,
  },
};
</script>

One-Way Data Flow

One-way data flow is a really awesome design in Vue that allows data to flow in just one direction from parent components to their children. By sticking to a one-way data flow, Vue.js keeps your app's data consistent and easy to predict, which means fewer bugs and simpler code to understand and take care of. Trying to set up a two-way binding might cause inconsistent data and some unwanted side effects. To make sure everything runs smoothly, use custom events (emits) or global state management for more complex stuff.

Example using custom events

Child

<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="sendMessage">Send Message to Parent</button>
  </div>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('messageSent', 'Hello from Child!'); // Emit an event with a custom message
    }
  }
};
</script>

This child component contains a button that, when clicked, emits an event with a custom message to the parent.

Parent

<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>Parent Component</h1>
    <p>Message from Child: {{ message }}</p>
    <ChildComponent @messageSent="updateMessage" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      message: '' // Initial message is empty
    };
  },
  methods: {
    updateMessage(newMessage) {
      this.message = newMessage; // Update the message in the parent component
    }
  }
};
</script>

When the child emits the messageSent event, the updateMessage method in the parent is triggered with the newMessage parameter, which updates the parent’s message data.

Conclusion

In this guide, we explored the awesomeness of Vue.js props for sharing data between components, with a special focus on parent-to-child communication using props, there are however some tips I would like to leave you with to help you stay a head of the matrix.

  1. Always Define Prop Types

Vue lets you define the prop types that the child will be receiving to ensure the data it gets from the parent is valid. If you fail to define the prop types you might end up experiencing some strange behavior. So to save you from hours of debugging runtime errors always define your prop types.

  1. Relying on Two-Way Data Binding

Vue props have a one way data flow, trying to set up two way data flow may lead to unwanted side effects. It is important to leave it as a one way data flow, but when you really have to, then use global state management or custom events

  1. Directly Modifying Props in Child Components

Avoid directly modifying props in child components, as this can cause data inconsistencies and unexpected outcomes.

Instead, treat props as read-only in child components.

  1. Not Defining Default Values

If a parent component doesn't supply a prop, Vue will give you a warning. To avoid that, it's always a nice idea to set default values for your props

Peace!

Jackson Obere

About Jackson Obere

I enjoy working with front-end technologies like Vue, React, and Vanilla JavaScript, with some Python on the side. I love building interactive web experiences and breaking down tricky concepts to make them easier to understand. I'm always curious and enjoy learning new things in the ever-evolving tech space.