Leveraging props to set the initial value of component data in Vue 3 Composition API

Currently, I am in the process of developing a search page in Vue 3 using the composition API. One of my components is responsible for displaying a snippet of data that includes specific keywords provided by the parent component. To achieve this, I need to create a displayable value based on the original data.

Initially, I made the mistake of assuming that simply fetching the props value like this would suffice:

setup(props) {

          const displayEntry = ref(props.entry)

...

However, this approach turned out to be reactive and caused unwanted changes to the original data. Since I don't require reactivity for this particular task as the component is dynamically created from the parent, storing a working copy of the data in the parent would only add unnecessary complexity to the code. After attempting various solutions to break the reactivity cycle, I finally found a simple solution:

displayEntry.value = props.entry

But then, my linter flagged an error:

error    Getting a value from the `props` in root scope of `setup()` will cause the value to lose reactivity  vue/no-setup-props-destructure

My question now is, what is the correct method to directly access the value from a prop without causing reactivity issues?

Answer №1

It turns out that the issue was caused by inadvertently passing a reference in the parent component. Here is the relevant code snippet:

setup(props) {
  watchEffect(() => {
      if (searchTerm.value == "") {
        filteredEntries.value = []
      } else {
        filteredEntries.value = entries.value.filter(searchFilter)
      }
    })

  return {
      searchTerm, filteredEntries, echo, showPreview
    }
}

The template section looks like this:

<SearchPreview
    v-for="( entry, index ) in filteredEntries"
    :key="index"
    :entry="entry"
    :search-term="searchTerm"
  />

I couldn't figure out why it was passing a ref instead of just the value, but I managed to resolve the issue within the component using this workaround:

const displayEntry = ref(JSON.parse(JSON.stringify(props.entry)))

(Note: Some nested properties remain undefined, but I passed them separately to ensure functionality)

Answer №2

You forgot to initialize fileredEntries as a ref in the code snippet provided. How are you populating it with values? If you're utilizing a data field on your component, it's recommended to move it to the setup function. Avoid mixing composition and options API, as they don't complement each other well.

Furthermore, you employed a (for ... in) loop to iterate through your filteredEntries. For an Array, it's more suitable to use a (for ... of) loop instead. (refer to What is the difference between ( for... in ) and ( for... of ) statements?)

Here's a refined example without any workarounds:

<template>
  <div>
    <SearchPreview
      v-for="( entry, index ) of filteredEntries"
      :key="index"
      :entry="entry"
      :search-term="searchTerm"
    />
  </div>
</template>
<script>

const MyComponent = defineComponent({
setup(props) {
  const entries = ref(['John', 'Jane']);
  const searchTerm = ref('');
  const filteredEntries = ref([]);
  const searchFilter = (item) => {
    // apply filtering logic here
  };

  watchEffect(() => {
      if (searchTerm.value == "") {
        filteredEntries.value = []
      } else {
        filteredEntries.value = entries.value.filter(searchFilter)
      }
    });

  return {
      searchTerm, filteredEntries
    };
  }
})

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

What is the process for retrieving information from my Google Analytics account to incorporate into my website?

Imagine being the proud owner of Your website is equipped with a Google Analytics script that diligently gathers data about your valuable visitors. Now, you have a desire to set up a page views counter. How can you extract data from your own account? ...

Working with AngularJS: Implementing a Service in a Controller

A service has been developed in AngularJS, but it is not being utilized in the controller. Service.js var appService = angular.module("appService", []); appService.service("bddService", function() { var bdds = bdd; this.getBdds = function(){ ...

"Angular File Upload Made Easy with Drag-and-Drop Functionality and Cleverly Positioned

Encountering an issue with Angular File upload in conjunction with relatively positioned elements. The drop target is set to 100% width and height, absolutely positioned. While dragging a file over any non-relatively positioned element, the overlay functio ...

What is the process of extracting a URL and inputting it into a form to enhance

Can anyone help with extracting a specific value (TEXT) from a URL and automatically paste it into an input form field? For example, if the URL is domain.com/page?code=123abc, I need to grab the code (in this case, 123abc) and have it automatically popula ...

timer-based user session expiration

Currently, the app I'm developing has a system where a session is created with a 15-minute expiration time once a user interacts with a form. This session is managed server-side. If the user remains idle for 15 minutes, the server returns a 404 erro ...

Slowly revealing sticky navigation with slideDown animation using JQuery

Here is the code for a .JS file: $(document).scroll(function (){ var menuheight= $('header').height(); var y = $(this).scrollTop(); if (y>(menuheight)) { $('.menu_nav_features').addClass ...

Update the icon with the adjusted API information

I am currently working on a website that revolves around the theme of weather. I have reached a point in the development process where I need the icon to change according to the current weather conditions. let updateIcon = () => { let ic ...

How do you display a nested object in React after merging it?

To display the JSON below as an image, click https://i.stack.imgur.com/tixu4.png let finalSplit = [ { start: "73", end: "76", splits: [ { word: "Now", start: "73", ...

The validation for the start and end dates in the datepicker is not functioning properly when

I have integrated a bootstrap date picker into my website. However, I am encountering an issue where the end date validation does not update when I change the start date after the initial selection. <script type="text/javascript" src="htt ...

AgGrid Encounters Difficulty in Recovering Original Grid Information

After making an initial API call, I populate the grid with data. One of the fields that is editable is the Price cell. If I edit a Price cell and then click the Restore button, the original dataset is restored. However, if I edit a Price cell again, the ...

Implementing IBAN as the default option in Stripe's PaymentElement

The functionality of the react-stripe-js library's IbanElement includes various options such as supportedCountries and placeholderCountry: <IbanElement ... options={{ supportedCountries: ["SEPA"], placeholderCountry: "DE& ...

Error: An unexpected identifier was encountered while executing my function

I've been trying to implement a function that I found online, but when I try to run it in the terminal, I keep getting this error: /home/simone/gekko/strategies/high.js:10 sma: function(name, price, points) ^^^ SyntaxError: Unexpected identifier I ...

What is the best way to send data into functions?

I'm trying to avoid using global variables and I'm facing some difficulties in figuring out how to pass the database variable into the addTrain function. Do I necessarily need to use global variables for the database? $(document).ready(function( ...

What is the reason behind the absence of certain fontAwesome icons?

I'm having trouble connecting Font Awesome in Vue.js ************* import { library } from '@fortawesome/fontawesome-svg-core' import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { faVuejs } from '@fortawesom ...

Learn how to upload an image using Vue.js and then trigger a custom method

Greetings! I am a newcomer to Vue.js and I have encountered a problem that I need help with. In my component, there is a hidden input for files. When I click a button, the browser displays a window for importing files from my PC. Once I choose a file, I wa ...

Challenges encountered when inserting nested data into MongoDB

I am currently in the process of constructing a database for a giveaway bot using MongoDB. When a new giveaway is initiated, the bot executes the following code to add the giveaway details to the database: const {mongoose} = require("mongoose") c ...

Filtering database records using a static dropdown list in MVC 5: A step-by-step guide

Is there a way to filter database records based on the columns QtyRecieved, QtyRecievedand Void using a static HTML dropdown list? The QtyRecieved and QtyRecievedand column are both decimal values, while Void is a boolean. This is what I have attempted: ...

Is there a way to fetch a file using the fs readFile function in node.js without explicitly stating the file name?

I'm currently facing a challenge in retrieving a file from the file system to send it via API to the client. I am using Express.js for my backend and utilizing the 'fs' library. My goal is to achieve this without explicitly specifying the fi ...

AngularJS: Modifying directive according to service value update

In my current application, I have a basic sidebar that displays a list of names fetched from a JSON call to the server. When a user clicks on a name in the sidebar, it updates the 'nameService' with the selected name. Once the 'nameService& ...

Leveraging the flexibility of an undefined variable as a useEffect dependency

Summary: Need help using listRef.current.clientWidth as a dependency in useEffect. I'm working on creating a dynamic list that automatically adjusts the width of its items based on the list's width. I've almost got it working, but I'm ...