Should objects passed as props be modified in Vue.js components?

I've observed that in Vue, object fields passed as Props can be changed, and these changes reflect in the parent component.

Is this considered a bad practice? Should it be avoided, or is it acceptable to use? What are the potential pitfalls of this approach?

For instance:

Parent.vue:

<script setup>
import { reactive } from 'vue';
import ChildInput from "./Child.vue";
</script>

<script>
const myObj = reactive({'val':'Default text'});
</script>

<template>
  <ChildInput :passedObj="myObj" />
  <div>
    It's a parent input: 
    <input v-model="myObj.val">
  </div>
</template>

Child.vue:

<script setup>
  const props = defineProps({
    passedObj: {
      type: Object,
      required: true,
    },
  })
  
  const dropValue = function() {
        props.passedObj.val = "Changed text";
  }
</script>

<template>
  <div>
    <label>
      It's a child input: 
      <input v-model="passedObj.val">
      <button @click="dropValue">Change text</button>
    </label>
  </div>
</template>

You can check out this example here.

Answer №1

Avoid shallow prop mutation as it is not allowed due to the read-only nature of props object.

Deep prop mutation is considered a poor practice that should be steered clear of according to Vue.js guidelines. This can complicate data flow and make tracking changes difficult, especially when done unconsciously. Another concern is potential performance impact since this falls outside typical use cases, though specific optimization issues are currently unknown.

The recommended approach is to utilize v-model two-way binding for mutating props. This way, mutations occur in the parent component and can be monitored through Vue events during debugging. When deep mutation of a prop occurs, it is cloned in the child component and emitted back to the parent.

Answer №2

It appears that utilizing this method may not be the best approach. Here is an alternative solution that I personally use with the Composition API.

If you only need to make changes to specific fields of a prop, you can employ a computed variable with setter and getter functions. Here's how:

In the parent component:

<script setup>
import { reactive } from "vue";
import InteractiveTable from "./Child.vue";

const myObj = reactive({
  data: [{name: "Sasha", address: "Middle of nowhere"}]
});
</script>

<InteractiveTable v-model="myObj" />

Remember that you are able to pass multiple v-models with custom titles using the syntax v-model:title. Alternatively, you can listen for events manually like so:

<InteractiveTable :passedObj="myObj" @update:passedObj="(data) => <something>" />

In the child component:

import { computed } from "vue";

const props = defineProps({
  modelValue: {
    type: Object,
    required: true,
  },
});

const emit = defineEmits([
  "update:modelValue",
]);

const localData = computed({
  get() {
    return props.modelValue.data;
  },
  set(val) {
    emit("update:modelValue.data", val);
  },
});

Now, you can utilize the following code:

const addRow = function (name, address) {
  localData.value.push({
    'name': name,
    'address': address,
  });
};

For more information on computed variables, click here. You can learn about emits here.

I am fairly new to Vue.js, so if you spot any errors in my code, please leave a comment to notify me.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Speeding up the loading time of my background images

body { background: url(http://leona-anderson.com/wp-content/uploads/2014/10/finalbackgroundMain.png) fixed; background-size:100% auto; } I have unique background images on each of my sites, but they are large in size and take some time to load due to bein ...

Pressing the button results in no action

I am currently developing a program that randomly selects 5 words from a database and inserts them into an array. Although the page loads correctly initially, nothing happens when the button is clicked. None of the alerts are triggered, suggesting that the ...

Tips on incorporating the vue package

I recently started using Vue and decided to incorporate a plugin called vue-toastr. I'm attempting to integrate it with Laravel, which already has Vue set up with the plugin. Unfortunately, I keep encountering an error that says "TypeError: Cannot rea ...

Unable to classify mapRef.current

I am facing an issue with my react component that contains a leaflet map. TypeScript is warning me about line mapRef.current.setView(coords, 13), stating it is an "unsafe call of an any typed value" import 'leaflet/dist/leaflet.css'; import { Map ...

Prevent clicking on a row within a cell in Vuetify's data-table

How can I display a dialog when clicking on a row in a vuetiy v-data-table? In addition, one column in this table has a button that should also trigger an action. Currently, if I click the button, both the row and the button triggers their respective acti ...

Incrementally add a new object to an existing array of objects

I have an array of objects below. When I do a console.log, this is what I see: [Object, Object, Object] 0:Object name: "Rick" Contact: "Yes" 1:Object name:"Anjie" Contact:"No" 2:Object name:"dillan" Contact:"Maybe" Now, I wa ...

Mastering the integration of dayjs within a Vue 3 application and component for optimal functionality

I have successfully integrated dayjs into a Vue3 component by including it in the data() function. import dayjs from 'dayjs' export default { data() { return { dayjs } } } While this method allows me to use dayjs within the te ...

Troubleshooting: Why is my Local Image not displaying in ReactJS

I am facing an issue with displaying images in my React application using an array of image paths. Below is the code snippet I have written: import React, { Component } from 'react'; class ItemsList extends Component { constructor() { ...

I'm struggling to solve a straightforward jQuery sliding issue

I am struggling to make text slide from right to left on my website. I want the text to appear only when the page loads or refreshes, and then slide off when a link is clicked, revealing new text. Can anyone help me figure this out? http://jsfiddle.net/XA ...

Difficulty in implementing Handlebars handler for dropdown onchange event

Currently, I am implementing Express alongside Handlebars for the front-end of my project. My aim is to trigger an event and read the value of the selected option in the dropdown within 'home.handlebars' when it changes, through 'index.js&ap ...

Guide for transferring information from JavaScript to PHP on the same page

My dilemma lies in transferring data from my JavaScript script to PHP code for use within a query. Despite numerous attempts, I have been unsuccessful in achieving this. Below is my script for uploading files using an input type: file, where the URL is sto ...

Changing the color of Material-UI's Toggle component: A step-by-step guide

After placing my Toggle button in the AppBar, I encountered an issue where both items were the same color when the Toggle was selected. Despite attempting various solutions (seen below), I have not been successful in changing its color. import React fr ...

I am noticing that my popover is causing my page to shift when I click it. It is expanding the width of my page more than I would

Upon clicking the user id popover on my page, it expands the page width instead of adjusting within the page boundaries. This is the issue: https://i.stack.imgur.com/EqaMo.png There's a small white space present that I want to eliminate. When the po ...

What is happening with the arrangement of $scope in Angular 1.x?

In my controller, I am loading content using ajax and want a spinner to appear while it's loading. The code snippet is as follows: <i class="fa fa-2x fa-spin fa-spinner" ng-show="isLoadingContent"></i> Accompanied by the following JavaSc ...

Is there a way to check if VueJs /Vuetify is currently in the middle of an animation?

When working with Angular and Jquery, it's easy to determine if something on the page is currently animating. By using the css selector ".ng-animating", you can check if any elements have the animating class applied to them. We rely on this functiona ...

Using Node.js to Send Emails via API

I've been grappling with an issue for over a week while trying to develop a web application that sends welcome emails to new subscribers. Despite my API code working perfectly, I cannot seem to get any output on the console indicating success or failu ...

Warning: npm is resolving peer dependency conflicts during the installation process

Upon running npm install for my React application, I encountered the following warnings in the logs. Despite that, the npm installation completed successfully and the dependencies were added under node_modules. My app even starts up without any issues. I ...

Receiving an error when attempting to import a function and access props using the "this" keyword: "TypeError: Unable to retrieve property 'renderElapsedString' as it is undefined"

Just started using React and working on a time tracking app based on the teachings of FullStackReact. Instead of Create Class, I opted for the ES6 'extends' module. However, I've encountered an error that has got me stumped. Error: Unable ...

Having trouble utilizing Reactjs Pagination to navigate through the data

I'm currently working on implementing pagination for a list of 50 records, but I'm encountering an issue. Even though I have the code below, it only displays 10 records and I'm unaware of how to show the next set of 10 records until all 50 a ...

Managing and displaying information provided through forms

I'm currently developing a URL shortening tool, but I'm encountering difficulties in extracting jQuery form values to generate the shortened URL text. You can view the form layout here: <form name="urlForm"> <input type="text" name ...