Encountered a TypeScript error in Vue 3 when attempting to access state within the setup method: "TS error -

Currently, I am working with Vue 3 and TypeScript. In the Setup function, I have defined some states like this:

export default defineComponent({
  setup() {
    const isLoadingSendData = ref(false)

    return { isLoadingSendData }
  
  },
  methods: {
    disableBtn(): boolean {
       // When using Webstorm, I encountered an error: TS2339: Property 'isLoadingSendData' doesn't exist 
       // on type 'disableBtn(): boolean'
       if(this.isLoadingSendData) {
         return // do something
       }
       return // do something
    }

  }
})

This is just one example of a particular scenario. The red error under this.isLoadingSendData in my IDE is confusing me. Can anyone provide insights on why this error occurs?

Answer №1

When using the composition API, you cannot directly access variables declared in the setup() function within options like methods and data. If you need to define a method within the composition API, the structure should be as follows:

export default defineComponent({
  setup() {
    const isLoadingSendData = ref(false);
    const disableBtn = (): boolean => {
      if (isLoadingSendData.value) {
        return; // do something
      }
      return; // do something
    };

    return { isLoadingSendData, disableBtn };
  }
});

If you prefer to use the options API instead, you can define it like this:

export default defineComponent({
  data() {
    return {
      isLoadingSendData: false
    };
  },
  methods: {
    disableBtn(): boolean {
      if (this.isLoadingSendData) {
        return; // do something
      }
      return; // do something
    }
  }
});

Therefore, the decision lies between using the composition API or the options API.

Another syntax option for the composition API is to use the <script setup> tag. Here is an example:

<script setup lang="ts">
import { ref } from "vue";

const isLoadingSendData = ref(false);
const disableBtn = (): boolean => {
  if (isLoadingSendData.value) {
    return; // do something
  }
  return; // do something
};
</script>

You can access everything declared within the <script setup> tag in the template section.

Answer №2

When utilizing Vue 3 with the setup function, there is no need to utilize the methods function as seen in Vue 2 and previous versions. Everything can be referenced directly in the template from the return object within the setup function. It's also important to wrap the script section with lang="ts" for TypeScript support.

<script lang="ts">
export default defineComponent({
  setup() {
    const isDataLoading = ref(false)

    return { isLoadingSendData }
  }
})
</script>

<template>
  <div v-if="isDataLoading">
    <p>Loading...</p>
  </div>
  <div v-else>
    <p>Finished Loading</p>
  </div>
</template>

Answer №3

Adding additional information to the existing answers, Vue3 offers a simpler option called setup script. I suggest using the Volar extension over Vetur for the most up-to-date Vue setup syntax

<script setup lang="ts">
import { ref, Ref, computed, ComputedRef } from "vue";

const isLoadingSendData: Ref<boolean> = ref(false);
//The `ref` above can be used in the template directly,
//or you can create a computed value if needed
const disableBtn: ComputedRef<boolean> = computed((): boolean => {
  return !isLoadingSendData.value
})
</script>

<template>
   <div>
      <button v-show="disableBtn">disabled button</button>
      <button v-show="!disableBtn">normal button</button>
   </div>
</template>

No need to explicitly return values as the setup script automatically provides them to the template. Rather than creating a function or computed property to check loading status, using the ref directly is recommended :)

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

How to capture the "chip close" event in Vuetify

Exploring the vuetify realm as a newcomer, I find myself grappling with event handling while working on my first web app project. Specifically, I am currently developing a "UserPicker" component using VAutocomplete. This component functions by sending an ...

Issues with implementing Dark mode in TailwindCSS with Nuxt.js

After spending a couple of days on this, I'm still struggling to get the dark mode working with Tailwind CSS in Nuxt.js. It seems like there might be an issue with the CSS setup rather than the TypeScript side, especially since I have a toggle that sw ...

The attribute 'XXX' is not found within the type 'IntrinsicAttributes & RefAttributes<any>'

My coding hobby currently involves working on a React website using TypeScript. I recently came across a free Material UI template and decided to integrate it into my existing codebase. The only challenge is that the template was written in JavaScript, cau ...

Techniques for adding data to an array using TypeScript

I am working on a project that involves creating a dynamic menu bar by fetching data from two different collections (supcat and cat) in order to combine them into a new array. However, I am encountering an issue with the push() method not working as expe ...

utilize a modal button in Angular to showcase images

I am working on a project where I want to display images upon clicking a button. How can I set up the openModal() method to achieve this functionality? The images will be fetched from the assets directory and will change depending on the choice made (B1, ...

TypeScript async function that returns a Promise using jQuery

Currently, I am facing a challenge in building an MVC controller in TypeScript as I am struggling to make my async method return a deferred promise. Here is the signature of my function: static async GetMatches(input: string, loc?: LatLng):JQueryPromise& ...

How can I convert duplicate code into a function in JavaScript?

I have successfully bound values to a view in my code, but I am concerned about the duplicate nested forEach loops that are currently present. I anticipate that Sonarcube will flag this as redundant code. Can anyone advise me on how to refactor this to avo ...

Encountering a 405 error when making an OpenAI API call with next.js, typescript, and tailwind CSS

I encountered a 405 error indicating that the method request is not allowed. I am attempting to trigger an API route call upon clicking a button, which then connects to the OpenAI API. Unsure of my mistake here, any guidance would be highly appreciated. E ...

What causes TypeScript to generate an error when using two array of object types, but not when using the shape of both?

There are two basic types of data available: type DataA = { percent: string; exchange: string; }; type DataB = { price: number; exchange: string; }; I'm puzzled as to why TypeScript gives errors when I try to use both types together: const ...

Guide on transforming the popup hover state into the active state in vue.js through a click event

My code currently includes a popup menu that shows up when I hover over the icon. However, I need to adjust it so that the popup changes its state from hover to active. Intended behavior: When I click the icon, the popup should appear and then disappear w ...

The Angular router is directed to an empty URL path instead of the specified URL

I have encountered a strange issue while developing my angular app which involves the router functionality. All routes were working perfectly fine until I discovered that after a successful login, instead of navigating to the '/admin' path as int ...

Is there a way to access the body html element within a template in vue.js?

I'm struggling to add styles to the body element of my HTML page. It seems like I can't access it directly from the template because there's another body element nested inside the main body. Even when I try to change the style using JavaScri ...

What is the reason for typescript's lack of a "function" type?

As a newcomer to TypeScript, I'm puzzled as to why I am unable to define an object like this: const obj: { property1: string property2: boolean property3: function } It seems that the only workaround is to use: const obj: { property1: strin ...

"Transforming a callback function to an asynchronous function results in an error

I have a piece of code that is functioning as expected: var smtpConfig = { host: 'localhost', port: 465, secure: true, // use SSL selfSigned: true }; // create reusable transporter object using the default SMTP ...

Indicate various file formats within the interface

Is there a way to define multiple file types in an interface? interface App { service: Record<ServiceName, Service> } For example, the ServiceName could be Cart, Product, User, etc. And the Service should be an imported object from a .ts file. ...

Leveraging the power of map in an Angular typescript file

I've been attempting to populate a Map in Angular by setting values dynamically. When certain buttons are clicked, the onClick function is invoked. typeArray: Map<number,string>; Rent(movieId: number){ this.typeArray.set(movieId,"Rental ...

React's setState function failed to update the specified value within the set

In attempting to update the state values, I encountered an issue where the state did not get updated as expected. To troubleshoot, I included console logs at each line of code. handleFilter=(event)=> { console.log(this.state.answerStatus) // In ...

Loading Angular page

I'm currently working on a personal project in Angular and I have a requirement to display a specific page for a brief period of time when the site is loaded, before redirecting to the home component. Is there a way to achieve this or create a loading ...

Obtain the query response time/duration using react-query

Currently utilizing the useQuery function from react-query. I am interested in determining the duration between when the query was initiated and when it successfully completed. I have been unable to identify this information using the return type or para ...

Encountering a cross-origin resource sharing (CORS) error while attempting

My Vue App is being hosted on an express server (nodejs running on port 60702) with the following setup: 'use strict'; const fs = require('fs'); const path = require('path'); const express = require('express'); var h ...