Unpacking and reassigning variables in Vue.js 3 using TypeScript

I am working with a component that has input parameters, and I am experimenting with using destructuring assignment on the properties object to reassign variables with different names:

<script setup lang="ts">
const { modelValue: isSelected, date1: inputDate1 } = defineProps({
  modelValue: Boolean,
  date1: String
})

console.log(isSelected)

const date1 = 'abc'
console.log(date1)
</script>

<template>
  <div v-if="isSelected">Selected!</div>
</template>

In this piece of code, the variable modelValue is being reassigned to isSelected, and date1 is being reassigned to inputDate1.

However, there are two issues that arise from this code.

While editing at line const date1 = 'abc', an error occurs:

Duplicate key 'date1'. This may lead to name collision in the script or template tag. eslintvue/no-dupe-keys

This error seems to be inaccurate. If we modify the code as follows:

const date2 = 'abc'
console.log(date1)

We encounter another error when trying to log date1:

Cannot find name 'date1'. Did you mean 'date2'? ts(2552)

It appears that there is no other variable with the same name as date1. So why does the compiler flag it as a duplicate?

Additionally, during runtime, an exception or warning is thrown from the template:

[Vue warn]: Property "isSelected" was accessed during render but is not defined on instance.

However, the line:

console.log(isSelected)

correctly outputs either true or false.

If we remove the destructuring variable reassignment, the code runs without errors:

<script setup lang="ts">
const { modelValue } = defineProps({
  modelValue: Boolean
})
console.log(modelValue)
</script>

<template>
  <div v-if="modelValue">Selected!</div>
</template>

The output of console.log(modelValue) remains consistent.
console.log(typeof modelValue) returns boolean.
console.log(typeof isSelected) also returns boolean.
So what exactly is causing the issue here?

Answer №1

First and foremost:

You cannot simply destructure props directly. The object returned by defineProps() is reactive, and breaking this reactivity by destructuring the object will result in the variables obtaining the current property values. To maintain reactivity, you must convert the object to refs using toRefs(), which can then be safely destructured.

Although I previously mentioned otherwise, there is now a feature known as "Reactive props destructure" (deprecated but available separately). This essentially means that the compiler transforms

const { prop: foo } = defineProps({ prop: String })
console.log(foo)

into

const __props = defineProps({ prop: String })
console.log(__props.prop)

Some individuals appreciate this change, while others find it confusing and counterintuitive. It's all subjective.

This modification tends to create confusion when typing. In the above example, even though foo appears to be a string, it actually possesses reactivity behind the scenes (unusual for a "bare" reactive primitive within a script block).


To simplify the first block of code:

<script setup lang="ts">
const { date1: inputDate1 } = defineProps({
  date1: String
})

const date1 = 'abc'
console.log(date1)
</script>

The issue here lies with:

Duplicate key 'date1'. May cause name collision in script or template tag. eslintvue/no-dupe-keys

Remember, props are automatically unwrapped in the template. They are accessible much like properties on window without explicitly stating window.; they exist at the top-level scope.

Since both the props and your defined variable share the same name (date1), conflicts arise due to ESLint's warning about possible collisions.

In your revised example:

const date2 = 'abc'
console.log(date1)

This leads to another error:

Cannot find name 'date1'. Did you mean 'date2'? ts(2552)

The reason behind this error is that props are only auto-unwrapped within the template context, not within the script itself. Therefore, date1 remains undefined in the script.


In addition, the line console.log(date1) displays the correct value during runtime.

While the output reflects the initial prop value, it lacks reactivity; the console.log() would not update even if it were. (There is partial reactivity involved, as discussed earlier.)


Addressing the next error:

[Vue warn]: Property "isSelected" was accessed during render but is not defined on instance.

I personally am unable to replicate this specific error message.

Perhaps it was a transient HMR glitch?


Without knowledge of your exact Vue version or configuration, I cannot delve further into the unrepeatable errors. If needed, share the complete code, configurations for replication, and preferably a link to a tool like Vue Playground or StackBlitz for better assistance.

During testing, I created a Vue Playground where you can experiment and view the compiled outcome.

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

Is there a way for me to retrieve the header values of a table when I click on a cell?

I have a project where I am developing an application for booking rooms using Angular 2. One of the requirements is to be able to select a cell in a table and retrieve the values of the vertical and horizontal headers, such as "Room 1" and "9:00". The data ...

Attempting to create a login and registration form

Hello, I am attempting to create a form that can generate new user accounts and passwords. These values should be stored from the input tag when the user clicks on the register button. Unfortunately, I am encountering an issue where clicking the register ...

React's memo and/or useCallback functions are not functioning as anticipated

Within my Home Component, there is a state called records, which I utilize to execute a records.map() and display individual RecordItem components within a table. function Home() { const [records, setRecords] = useState<Array<RecordType>>(l ...

When using the .append method in jQuery, the JSON array only displays the last value of the array when iterating through it with

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>Displaying Array Data in Table Using Javascript</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">& ...

Using Node.js to write data to a JSON file

Currently, I am working on a program that scans through an array containing numerous links. It reads through each link, extracts specific text, and then stores it in an output file as JSON. However, I am facing an issue with formatting the JSON file. The ...

Using JavaScript and HTML, create a click event that triggers a drop-down text

Can anyone help me with creating a dropdown feature using JavaScript, HTML, and CSS? I want to be able to click on the name of a project and have information about that project show up. Any suggestions on how I can achieve this? Thanks in advance! ...

Show specific content based on which button is selected in HTML

I am working on a project where I have three buttons in HTML - orders, products, and supplier. The goal is to display different content based on which button the user clicks: orders, products, or supplier information. function showData(parameter){ i ...

Adjust Column Title in Table

Is it possible to customize the column headers in a mat-table and save the updated value in a variable? I've been looking for a solution to this but haven't found one yet. ...

What is the best way to transfer data between functions?

I'm working on a fun Santa's game to play with my friends. The concept is simple: you enter your name, click a button, and a random name from the list will be displayed as the result. I've encountered a couple of challenges: I can succe ...

Trigger an Ajax request upon user confirmation, which will only be prompted based on the result of a previous Ajax call

Currently, I am facing a challenging issue surrounding asynchronous calls: A specific JQuery function is triggered on user click. This function then requests a PHP file to check if the user input overlaps with existing information in the database. If an o ...

Changing ch to Px in CSS

Important Notes: I have exhaustively explored all the questions and answers related to this particular topic. The question I have is very straightforward: How many pixels are equivalent to 1 character? Here's a sample of my code - code Related Sear ...

Is there a way to implement field validation in a Vue wizard form?

Trying to implement form validation using Joi in a Vue wizard form, but not sure how to set it up correctly. The objective is to control the fields before progressing to the next and final page using the next() method. I want to keep the simplicity of th ...

Why am I unable to alter the variable value within the callback event?

Exploration of Request Handling POST request To /api/endpoint headers: standard body: data=test123 POST response From /api/endpoint headers: standard body: data=test123 expectation(NOT MET): Show the request body content in the console. reality(FRU ...

The Facebook Comments feature on my React/Node.js app is only visible after the page is refreshed

I am struggling with getting the Facebook Comment widget to display in real-time on my React application. Currently, it only shows up when the page is refreshed, which is not ideal for user engagement. Is there a way to make it work through server-side r ...

JavaScript rearrange array elements

Currently, I'm attempting to move the values of an array over by a random amount. For instance: var array = [1,2,3,4]; var shiftAmount = 1; The goal is to shift the array so that it looks like [4,1,2,3] ...

Display one div and conceal all others

Currently, I am implementing a toggle effect using fadeIn and fadeOut methods upon clicking a button. The JavaScript function I have created for this purpose is as follows: function showHide(divId){ if (document.getElementById(divID).style.display == ...

I am unable to add a new property to the request object in the Express framework

My goal is to add a new property to the request object in typescript. Here's the code snippet I'm using: import { request, Request, response, Response } from "express"; ((req: Request, res: Response) => { console.log(req.user); ...

Attempting to retrieve data from HTML in VueJS using two distinct variables

Here's the issue I'm facing: I have two arrays. The first one, which we'll call A, looks like this: [{id: 2, otherValue: "hello"}] The second array, which we'll call B, looks like this: [{1: {title: "title1", text: "message1"}, 2: {t ...

Transmit text from tinyMCE through AJAX in MVC architecture with PHP

I am currently facing an issue while trying to send POST data in the form of an array containing email elements such as subject and message. The problem arises when using tinyMCE for the subject part, which is not being sent through successfully. All other ...

Sending parameters from one Node.js function to another in separate JavaScript files

I am currently working on passing function responses between two Node.js scripts. Here is my approach. Index.js var express = require('express'); require('./meter'); var app = express(); app.get('/',function(req,res){ ...