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

Adding a new value to an array of objects without altering the existing values in ReactJS and NextJS

I have a JSON file containing image names that I need to organize into a Key-Value Object. I am currently using regex to create keys by removing "-img[image No]". However, I am having trouble storing all the image names in the array without overwriting pre ...

Display the HTML output using a Vue template tag without incorporating a nested element

I am exploring how to display inner HTML in Vue while looping through a collection without needing to wrap it in an additional div or span. Essentially, I have an array of JavaScript objects in a Vue template. Each object has a "render" method that genera ...

You cannot access the property 'subscribe' on a void type in Angular 2

fetchNews(newsCategory : any){ this.storage.get("USER_INFO").then(result =>{ this.storage.get("sessionkey").then(tempSessionKey =>{ this.email = JSON.parse(result).email; this.newSessionKey = tempSessionKey; this.authKey =JSON.stringify("Basic ...

Using JavaScript to toggle the iron-collapse property

I've implemented multiple <iron-collapse> elements with unique IDs, each one corresponding to a <paper-icon-button>. On screens wider than 650px, I can interact with the <iron-collapse>s using their respective buttons. But on narrow ...

Performing bulk operations on multiple documents in MongoDB by specifying a custom identifier for updating or

Recently, I've been working with a mongo schema const taskSchema=new Schema({ userID:{type:ObjectId,required:true}, task: { type: String, required: true, trim: true, maxlength: 30, }, finalDate:{type:Date,required:true}, ...

Is there a way to view the contents of the dev server once it has been bundled by webpack?

From my understanding, webpack in dev mode stores all imported files in a certain location and then serves the bundle.js file to the client. If the code inside bundle.js requests a CSS file, the css-loader should have already been configured to provide t ...

Is it possible to generate a PNG blob using binary data stored in a typed array?

I have a piece of binary data that is formatted as a PNG image. I am looking to convert it into a blob, generate a URL for the blob, and then showcase it as an image in various places where an image URL can be used, such as CSS. My initial approach invol ...

Stop receiving notifications for channel events in Stream with the GetStream.io Chat API

I'm having trouble understanding how to stop listening for channel events in JavaScript using the Stream Chat API. According to the documentation: // remove the handler for all "message.new" events on the channel channel.off("message.new", myChanne ...

Is one round the limit for my JavaScript image slider?

After studying the JavaScript Chapter on W3Schools, I attempted to create an image slider. Initially, everything worked perfectly for the first cycle. For instance, when I clicked the next button, the slides continued to slide until the end of the slidesho ...

Can you explain the purpose of $winstonLoggerConfig<T>() and $winstonLogger<T>() in winston v3?

I'm currently using the winston logger and I want to implement flow typing for it. However, I am unsure of what exactly I should pass to it in order to achieve this. Below is my current logger setup: const logger = createLogger({ ... }); Missing typ ...

"Exploring the possibilities of customizing Material UI tabs and implementing a tabs scroller

I'm currently trying to customize the appearance of these MUI tabs, specifically the tab color and bottom border color. Despite my attempts using makeStyles and other methods, I haven't been able to achieve the desired result. Here is an example ...

Common JavaScript Framework Startup Errors

Currently, I am delving into the world of JavaScript and experimenting with various thingamajigs. Could someone kindly shed some light on why my script is throwing errors? // Effects object var effects = { // Display an object show : function(obj) { o ...

Retrieve JSON encoded data from a separate AJAX request

Currently utilizing prestashop 1.6, I have a specific ajax function where I encode data that is successfully retrieved on the console using echo. Now, my task is to decode this JSON data in another ajax function in order to extract a value for a particular ...

transferring information between pages in nextjs

Currently in the process of developing a website, specifically working on a registration page for user sign-ups. My main challenge at the moment is validating email addresses without using Links. I need to redirect users to a new page where they can see if ...

Getting started with TinyMCE in Nuxt: A step-by-step guide

I need to incorporate this script into my Nuxt code: <script> tinymce.init({ selector: "#mytextarea", plugins: "emoticons", toolbar: "emoticons", toolbar_location: "bottom", menubar: false ...

Execute JavaScript code once all the AngularJS template directives are fully loaded

On my HTML page, I am utilizing AngularJS template directives. Here is an example of how it looks: <div class="row"> <div class="col-sm-12"> <div logo></div> <div login-card></div> ...

Guide on implementing Regular Expressions in Directives for validation in Angular 8

Managing 8 different angular applications poses its unique challenges. In one of the applications, there is a directive specifically designed for validating YouTube and Vimeo URLs using regular expressions. Unfortunately, once the RegExp is declared, ther ...

Simple steps to turn off error highlighting for TypeScript code in Visual Studio Code

Hey there! I've encountered an issue with vscode where it highlights valid code in red when using the union operator '??' or optional chaining '?.'. The code still builds without errors, but vscode displays a hover error message st ...

"Issue with Material-ui Autocomplete where the defaultValue does not function properly

The defaultValue was set to "Chairs" but it doesn't seem to be working as expected. Here is the code snippet: import React, { useState } from "react"; import TextField from "@mui/material/TextField"; import Autocomplete from "@mui/material/Autocomple ...

Asynchronous waterfall call in Node.js to call the method before

Is it possible to invoke a previous method within async.waterfall from a subsequent method? async.waterfall([ function (callback) { }, function (reservationStatus, callback) { }, function (reservationStatusList, f ...