Home

Mastering Vue refs: From Zero to Hero

Well-designed reactivity is one of the selling points of Vue. When a reactive value is updated then automagically the components using the reactive value are updated.

refs, created by ref() composition API, are the primary tool of Vue reactivity. Knowing refs is a requirement if you want to understand reactivity.

Let's see how refs and ref() API work in Vue.

Before I go on, let me recommend something to you.

Using Vue composition API is fun... but sometimes challenging. Take "Vue 3 Composition API" course by Vueschool to become proficient in Vue composition and reactivity in just a few weekends!

Table of Contents

1. how to create refs, 2. how to update refs, 3. refs in setup(), 4. objects in refs, 5. access dom elements, 6. how to watch refs, 7. computed() and refs, 8. conclusion.

ref() reactivity API lets you create simple reactive values. The ref is reactive because changing its value re-renders the component to show the update value in the output.

ref(initialValue) is called as a regular function and accepts an optional argument as the initial value. ref() returns a special object called ref (which is the reactive value).

Open the demo.

ref(0) creates and returns a ref initialized with 0 . The ref is stored in the variable count for later use.

The value of the ref is accessed by reading the special property count.value that is available on all the refs. count.value is currently 0 because that's the initial value of the ref.

You can omit .value property inside the template <div>{{ count }}</div> because in the template the ref value is automatically unwrapped.

A ref can be created inside:

  • <script setup>
  • setup() method
  • or inside of a composable function

but accessed anywhere, including the template.

The true benefit of refs shows when you update them and see how Vue magically re-renders the component to reflect the changes.

Updating a ref is easy: just change the value of myRef.value = 'New Value' property.

You can update a ref value anywhere you want. But usually, you'll update refs inside event handlers.

Let's implement a scenario having a button and a count state. When the user clicks the button, the count state increases by one. The actual value of the count (even if it changes) needs to be rendered on the screen.

You can see in the scenario the need for reactivity : the screen needs to show the actual value of the count. Using a ref fits well:

Open the demo. You'll see that count is 0 .

Click Increase button and count increases. Importantly, the most actual value of the count is rendered on the screen. That's reactivity in action.

count is a ref and also a reactive value. When count.value changes, Vue updates the component and shows the new count value on the screen. Pure magic!

The composition API can be used inside <script setup> (see the previous examples), but also inside the setup() method of options API.

I like <script setup> because it's shorter and more expressive than setup() . But that's me.

Either way, you can also use ref() inside the setup() method if that's your preference:

The behavior of ref() is almost the same in <script setup> as in setup() {...} . There are just 3 differences to remember.

First, don't forget to return the ref from the setup() method: return { count } . Otherwise, it won't be accessible in the component methods and template.

Second, you have to access the ref using this keyword. For example, this.count accesses the ref (not directly count ) inside the onClick method.

Third, the refs are automatically unwrapped when accessed inside the options API methods. Access and update the value of a ref using this.count (not using this.count.value ).

In the examples above I've created the count ref that operated on numbers. In general, refs can store any primitive value: numbers, strings, booleans, undefined , or null .

refs can also store complex data structures like objects, arrays, maps, and even DOM elements.

Let's store in a ref a plain JavaScript object { name: 'Batman' } :

ref({ name: 'Batman' }) creates a ref that stores an object. You can access the object from the ref using hero.value . And also access any properties of that object using regular property accessors: hero.value.name .

Moreover, the object stored in a ref automagically becomes reactive ! Plus the reactivity is applied deeply on nested objects or arrays.

Let's update the hero name from 'Batman' to 'Joker' when a button is clicked:

Since hero ref is reactive, the change hero.value.name = 'Joker' is also reflected on the screen by changing from 'Batman' to 'Joker' .

Changes to an object in ref are deeply reactive.

Side note: if you don't want deeply reactive refs, consider using shallowRef() API.

Usually, you don't have to access and manipulate DOM elements directly. Just let Vue take care of everything regarding DOM.

But there are situations when you need to access DOM elements. For example, when integrating a 3rd party code that isn't Vue-aware.

Vue uses refs to give you access to DOM elements.

There are only 3 steps to make a ref access a DOM element:

  • Define the ref supposed to hold the element: const element = ref()
  • Inside the template, use the special attribute ref and assign the ref to it: <div ref={element}>...</div>
  • After mounting, you can access the element by reading element.value

Let's continue with a simple example.

A common case when you need to access an element is to focus an input field as soon as it is rendered:

const input = ref() creates the placeholder ref, which later will contain the input element.

When rendering the input element inside the template, please use ref attribute and assign to it the ref: <input ref="input" type="text" /> .

Finally, after component mounting, you can freely access the input element and call the input method on it: input.value.focus() .

The moment when the component mounts is captured using the onMounted() hook. Only after mounting you are guaranteed that the input ref links to the element.

If you accidentally access input before mounting, then input.value is undefined .

watch() API watches ref value change.

watch(myRef, callback) : set the ref as the first argument myRef and the second argument as the callback callback to be invoked when the ref changes.

Let's log to console a message 'myRef changed' when myRef value changes:

Clicking Change ref button changes myRef value to 10 . As result watch() invokes the callback and logs to console 'myRef changed' message.

You can invoke inside of the watcher different kinds of side effects — for example, initiate fetch requests.

By default watch(myRef, callback) watches only the direct change of value property of myRef .

If you want to watch deep changes of a ref (e.g. when an object or arrays contents is changed), then set the third argument as { deep: true } :

In the examples presented until now, I've created refs explicitly: using ref() factory function provided by Vue.

But other reactivity APIs can create refs implicitly. A common API creating refs is computed() .

const computedRef = computed(calc) accepts a callback function calc that uses reactive values to calculate a value. The calculated value is returned as a ref.

Let's create a computed ref evenOdd that changes to 'even' or 'odd' depending on the count ref value:

evenOdd = computed(() => count.value % 2 === 0 ? 'even' : 'odd') creates a ref which depending on count.value number changes to 'even' or 'odd' .

You can use multiple refs, even mixed with reactive objects, to create computed refs:

sum is a computed ref which is a sum of 2 refs and one reactive object property (created using reactive() API: an alternative to refs).

When any reactive value used inside computed() callback changes, the value of sum ref recalculates reactively.

ref() is a factory function that creates special reactive values in Vue: refs.

const myRef = ref(initialValue) accepts as the first argument the initial value of the ref, then returns the newly created ref.

To access the value stored inside a ref just read myRef.value property. To change the ref value update myRef.value = 'New value' property.

Refs in Vue are reactive values. Meaning that if you render in the template a ref value, then changing the ref programmatically makes Vue re-render the output to reflect the ref change.

A ref gives direct access to a DOM element rendered in the template. To make ref access a DOM element, assign ref attribute with a ref: <div ref="myRef"> . After component mounting, myRef.value will contain the DOM element.

Vue can also create refs implicitly: for example computed() API returns a ref.

Last but not least watch() API lets you detect when a ref value changes: watch(myRef, callback) .

When would you use ref() and when reactive() ? Share your opinion in a comment!

Like the post? Please share!

Dmitri Pavlutin

About Dmitri Pavlutin

Popular posts.

Vue 3 Composition API - "ref" and "reactive"

Lindsay Wardell

Lindsay Wardell

Mar 23, 2021

Introduction

With the release of Vue 3, developers now have access to the Composition API, a new way to write Vue components. This API allows features to be grouped together logically, rather than having to organize your single-file components by function. Using the Composition API can lead to more readable code, and gives the developer more flexibility when developing their applications.

The Composition API provides two different ways to store data locally in the component - “ref” and “reactive”. These two methods serve a similar role as the “data” function in the traditional Options API that is commonly used in Vue applications today. In this article, we will explore both of these new methods, and when to use them in your own application.

If you want to read more about the Composition API, you can read this article by Bilal Haidar for an overview.

You can view the code examples below in a working app on CodeSandbox by clicking this link .

Options API - data

If you have used Vue in the past, you have probably seen how different parts of your components are divided by function. Each single-file component has access to a number of attributes: data, computed, methods, lifecycle hooks, and so on. This is referred to as the "Options API". Below is an example application implementing local state with the Options API:

Composition API - ref

Now let's look at the same example as above, using the Composition API. First, we'll take a look at ref . From the Vue 3 documentation :

ref takes an inner value and returns a reactive and mutable ref object. The ref object has a single property .value that points to the inner value.

Below is our example code using ref :

Let's take a closer look. What changed between these two examples?

  • Rather than using the data function to add local state, we are using the setup function. This new function replaces data , beforeCreate , and created , and is the place for utilizing the Composition API.
  • Like with data , setup returns an object. The contents of that object is any variable that needs to be accessible from the template. Since we want the count to be available in the template, we include it in the return object.

Before we continue to reactive , we should make one more change. Let's move the click event into its own method, rather than performing the action in the template.

Unlike in the Options API, methods are simply functions. We don't need any special syntax or Composition API methods to make them work. However, just like the count variable above, we do need to return the method from the setup function in order for it to be available in the template.

Notice that in the template, we used count++ to increase the value, but in the setup function, we use count.value . This is because in the setup function, count has a type of Ref<number> , where in the template the internal value is directly available.

Composition API - reactive

Now let's try out the reactive method. From the Vue 3 docs :

reactive returns a reactive copy of the object. The reactive conversion is "deep"—it affects all nested properties. In the ES2015 Proxy based implementation, the returned proxy is not equal to the original object. It is recommended to work exclusively with the reactive proxy, and avoid relying on the original object.

Here is our code example using reactive instead of ref :

Within the setup function, we can use the return value of reactive very similarly to how we use the data function in the Options API. Because the object is deeply reactive, we can also make changes to it directly. So instead of count.value++ , we can simply increment the value with state.value++ .

When to use ref and reactive

In general, ref is useful for primitives (string, number, boolean, etc), and reactive is useful for objects and arrays. However, there are some key points to consider:

First, if you pass an object into a ref function call, it will return an object that has been passed through reactive . The below code works perfectly fine:

Second, while the object returned from reactive is deeply reactive (setting any value to the object will trigger a reaction in Vue), you can still accidentally make the values non-reactive. If you try to destructure or spread the values of the object, for example, they will no longer be reactive. The below code does not work as you might expect:

If you want to do something like this, Vue 3 has you covered. There are a number of functions to convert between Refs and their values. In this case, we will use the toRefs function. From the docs:

Converts a reactive object to a plain object where each property of the resulting object is a ref pointing to the corresponding property of the original object.

If we update our above code example to spread the result of toRefs , then everything works as we'd expect:

There are other ways to combine these two functions, both with setting a value in a reactive object to its own variable with toRef or adding a ref to an object directly. ref and reactive are two parts of the solution, and you will find yourself reaching for each of them as needed.

The Vue 3 Composition API provides a lot of benefit to developers. By allowing features to be grouped together, rather than functions, developers can focus on what they are building, and less on fitting their code into a predetermined structure.

By leveraging the ref and reactive functions to maintain local state, developers have new tools to write more maintainable and readable code. These methods work well together, rather than one or the other, each solving a different problem.

Remember that the Composition API is optional! The existing Options API is not going anywhere, and will continue to work as expected. I would encourage you to try out the Composition API, and see how these new methods can improve your own workflow and applications.

To view the above examples in a working application, click here to view them in CodeSandbox.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

Author Lindsay Wardell

Lindsay is a software engineer at This Dot Labs, and a host on the podcast Views on Vue. She loves learning about new languages and tools, and sharing that knowledge with the community.

You might also like

3 VueJS Component Libraries Perfect for Beginners cover image

3 VueJS Component Libraries Perfect for Beginners

For developers checking out VueJS for the first time, the initial steps are overwhelming, particularly when setting up projects from square one. But don’t worry! The VueJS ecosystem offers a plethora of remarkable component libraries, easing this early obstacle. These three libraries are pre-built toolkits, providing beginners with the means to kickstart their VueJS projects effortlessly. Let’s take a look! Quasar Quasar is among the most popular open-source component libraries for Vue.js, offering a comprehensive set of ready-to-use UI components and tools for building responsive web applications and websites. Designed with performance, flexibility, and ease of use in mind, Quasar provides developers with a wide range of customizable components, such as buttons, forms, dialogs, and layouts, along with built-in support for themes, internationalization, and accessibility. With its extensive documentation, active community support, and seamless integration with Vue CLI and Vuex, Quasar empowers developers to rapidly prototype and develop high-quality Vue.js applications for various platforms, including desktop, mobile, and PWA (Progressive Web Apps). PrimeVue PrimeVue is a popular Vue.js component library offering a wide range of customizable UI components designed for modern web applications. Developed by PrimeTek, it follows Material Design guidelines, ensuring responsiveness and accessibility across devices. With features like theming, internationalization, and advanced functionalities such as lazy loading and drag-and-drop, PrimeVue provides developers with the tools to create elegant and high-performing Vue.js applications efficiently. Supported by clear documentation, demos, and an active community, PrimeVue is an excellent choice for developers seeking to streamline their development process and deliver polished user experiences. Vuetify Vuetify is a powerful Vue.js component library that empowers developers to create elegant and responsive user interfaces with ease. Built according to Google's Material Design guidelines, Vuetify offers a vast collection of customizable UI components, ranging from buttons and cards to navigation bars and data tables. Its comprehensive set of features includes themes, typography, layout grids, and advanced components like dialogues and sliders, enabling developers to quickly build modern web applications that look and feel polished. With extensive documentation, active community support, and ongoing development, Vuetify remains a top choice for Vue.js developers seeking to streamline their workflow and deliver visually stunning user experiences. For newcomers venturing into Vue.js, the initial setup might seem daunting. Thankfully, Vue.js offers a variety of component libraries to simplify this process. Quasar, PrimeVue, and Vuetify are standout options, each providing pre-built tools to kickstart projects smoothly. Whether you prefer Quasar's extensive UI components, PrimeVue's Material Design-inspired features, or Vuetify's responsive interfaces, these libraries cater to diverse preferences and project requirements. With their clear documentation and active communities, these libraries empower developers to start Vue.js projects confidently and efficiently, enabling Vue developers to create polished user experiences....

May 1, 2024

Understanding Vue's Reactive Data cover image

Understanding Vue's Reactive Data

Introduction Web development has always been about creating dynamic experiences. One of the biggest challenges developers face is managing how data changes over time and reflecting these changes in the UI promptly and accurately. This is where Vue.js, one of the most popular JavaScript frameworks, excels with its powerful reactive data system. In this article, we dig into the heart of Vue's reactivity system. We unravel how it perfectly syncs your application UI with the underlying data state, allowing for a seamless user experience. Whether new to Vue or looking to deepen your understanding, this guide will provide a clear and concise overview of Vue's reactivity, empowering you to build more efficient and responsive Vue 3 applications. So, let’s kick off and embark on this journey to decode Vue's reactive data system. What is Vue's Reactive Data? What does it mean for data to be ”'reactive”? In essence, when data is reactive, it means that every time the data changes, all parts of the UI that rely on this data automatically update to reflect these changes. This ensures that the user is always looking at the most current state of the application. At its core, Vue's Reactive Data is like a superpower for your application data. Think of it like a mirror - whatever changes you make in your data, the user interface (UI) reflects these changes instantly, like a mirror reflecting your image. This automatic update feature is what we refer to as “reactivity”. To visualize this concept, let's use an example of a simple Vue application displaying a message on the screen: ` In this application, 'message' is a piece of data that says 'Hello Vue!'. Let's say you change this message to 'Goodbye Vue!' later in your code, like when a button is clicked. ` With Vue's reactivity, when you change your data, the UI automatically updates to 'Goodbye Vue!' instead of 'Hello Vue!'. You don't have to write extra code to make this update happen - Vue's Reactive Data system takes care of it. How does it work? Let's keep the mirror example going. Vue's Reactive Data is the mirror that reflects your data changes in the UI. But how does this mirror know when and what to reflect? That's where Vue's underlying mechanism comes into play. Vue has a behind-the-scenes mechanism that helps it stay alerted to any changes in your data. When you create a reactive data object, Vue doesn't just leave it as it is. Instead, it sends this data object through a transformation process and wraps it up in a Proxy. Proxy objects are powerful and can detect when a property is changed, updated, or deleted. Let's use our previous example: ` Consider our “message” data as a book in a library. Vue places this book (our data) within a special book cover (the Proxy). This book cover is unique - it's embedded with a tracking device that notifies Vue every time someone reads the book (accesses the data) or annotates a page (changes the data). In our example, the reactive function creates a Proxy object that wraps around our state object. When you change the 'message': ` The Proxy notices this (like a built-in alarm going off) and alerts Vue that something has changed. Vue then updates the UI to reflect this change. Let’s look deeper into what Vue is doing for us and how it transforms our object into a Proxy object. You don't have to worry about creating or managing the Proxy; Vue handles everything. ` In the example above, we encapsulate our object, in this case, “state”, converting it into a Proxy object. Note that within the second argument of the Proxy, we have two methods: a getter and a setter. The getter method is straightforward: it merely returns the value, which in this instance is “state.message” equating to 'Hello Vue!' Meanwhile, the setter method comes into play when a new value is assigned, as in the case of “state.message = ‘Hey young padawan!’”. Here, “value” becomes our new 'Hey young padawan!', prompting the property to update. This action, in turn, triggers the reactivity system, which subsequently updates the DOM. Venturing Further into the Depths If you have been paying attention to our examples above, you might have noticed that inside the Proxy method, we call the functions track and trigger to run our reactivity. Let’s try to understand a bit more about them. You see, Vue 3 reactivity data is more about Proxy objects. Let’s create a new example: ` In this example, when you click on the button, the message's value changes. This change triggers the effect function to run, as it's actively listening for any changes in its dependencies. How does the effect property know when to be called? Vue 3 has three main functions to run our reactivity: effect, track, and trigger. The effect function is like our supervisor. It steps in and takes action when our data changes – similar to our effect method, we will dive in more later. Next, we have the track function. It notes down all the important data we need to keep an eye on. In our case, this data would be state.message. Lastly, we've got the trigger function. This one is like our alarm bell. It alerts the effect function whenever our important data (the stuff track is keeping an eye on) changes. In this way, trigger, track, and effect work together to keep our Vue application reacting smoothly to changes in data. Let’s go back to them: ` Tracking (Dependency Collection) Tracking is the process of registering dependencies between reactive objects and the effects that depend on them. When a reactive property is read, it's "tracked" as a dependency of the current running effect. When we execute track(), we essentially store our effects in a Set object. But what exactly is an "effect"? If we revisit our previous example, we see that the effect method must be run whenever any property changes. This action — running the effect method in response to property changes — is what we refer to as an "Effect"! (computed property, watcher, etc.) > Note: We'll outline a basic, high-level overview of what might happen under the hood. Please note that the actual implementation is more complex and optimized, but this should give you an idea of how it works. Let’s see how it works! In our example, we have the following reactive object: ` We need a way to reference the reactive object with its effects. For that, we use a WeakMap. Which type is going to look something like this: ` We are using a WeakMap to set our object state as the target (or key). In the Vue code, they call this object targetMap. Within this targetMap object, our value is an object named depMap of Map type. Here, the keys represent our properties (in our case, that would be message and showSword), and the values correspond to their effects – remember, they are stored in a Set that in Vue 3 we refer to as dep. Huh… It might seem a bit complex, right? Let's make it more straightforward with a visual example: With the above explained, let’s see what this Track method kind of looks like and how it uses this targetMap. This method essentially is doing something like this: ` At this point, you have to be wondering, how does Vue 3 know what activeEffect should run? Vue 3 keeps track of the currently running effect by using a global variable. When an effect is executed, Vue temporarily stores a reference to it in this global variable, allowing the track function to access the currently running effect and associate it with the accessed reactive property. This global variable is called inside Vue as activeEffect. Vue 3 knows which effect is assigned to this global variable by wrapping the effects functions in a method that invokes the effect whenever a dependency changes. And yes, you guessed, that method is our effect method. ` This method behind the scenes is doing something similar to this: ` The handling of activeEffect within Vue's reactivity system is a dance of careful timing, scoping, and context preservation. Let’s go step by step on how this is working all together. When we run our Effect method for the first time, we call the get trap of the Proxy. ` When running the get trap, we have our activeEffect so we can store it as a dependency. ` This coordination ensures that when a reactive property is accessed within an effect, the track function knows which effect is responsible for that access. Trigger Method Our last method makes this Reactive system to be complete. The trigger method looks up the dependencies for the given target and key and re-runs all dependent effects. ` Conclusion Diving into Vue 3's reactivity system has been like unlocking a hidden superpower in my web development toolkit, and honestly, I've had a blast learning about it. From the rudimentary elements of reactive data and instantaneous UI updates to the intricate details involving Proxies, track and trigger functions, and effects, Vue 3's reactivity is an impressively robust framework for building dynamic and responsive applications. In our journey through Vue 3's reactivity, we've uncovered how this framework ensures real-time and precise updates to the UI. We've delved into the use of Proxies to intercept and monitor variable changes and dissected the roles of track and trigger functions, along with the 'effect' method, in facilitating seamless UI updates. Along the way, we've also discovered how Vue ingeniously manages data dependencies through sophisticated data structures like WeakMaps and Sets, offering us a glimpse into its efficient approach to change detection and UI rendering. Whether you're just starting with Vue 3 or an experienced developer looking to level up, understanding this reactivity system is a game-changer. It doesn't just streamline the development process; it enables you to create more interactive, scalable, and maintainable applications. I love Vue 3, and mastering its reactivity system has been enlightening and fun. Thanks for reading, and as always, happy coding!...

Nov 22, 2023

Building Web Components with Vue 3.2 cover image

Building Web Components with Vue 3.2

Introduction Have you ever worked across multiple projects, and wanted a set of custom components you could just leverage across all of them? Whether for a job or just for side projects, having a suite of components you can reach for is an excellent way to get going faster in a new or existing project. But what if not all of your projects are using the same UI framework? Or, what if you have one that isn't using any JavaScript framework at all, and is completely server-rendered? As a Vue developer, ideally we would like to just use our framework of choice to build complex user interfaces. But sometimes we find ourselves in the above situation, working with another JavaScript framework such as React or Angular, or using a backend rendering system like Rails or Laravel. How can we build a reusable UI across these various frontend options? In Vue 3.2, we now have a solution to this problem: Web Components, powered by Vue! Web Components According to MDN, "Web Components is a suite of different technologies allowing you to create reusable custom elements — with their functionality encapsulated away from the rest of your code — and utilize them in your web apps." Consider a few existing elements in HTML, such as select or video. These interactive elements contain their own basic styling (typically provided by the browser), some internal logic, and a way to listen to events. Web Components allow developers to build their own elements, and reference them in their HTML - no framework required. Here's a very basic web component example of a component that would display the current time. ` Once a custom Web Component has been defined, they can be rendered as part of the DOM, just like any standard HTML element. We can use this element in our HTML like this: ` We can also use custom attributes with these elements, allowing us to pass data into them (similar to props in Vue). Note that objects cannot be passed in as attributes, because that is a JavaScript concept, not an HTML feature. ` While we could write this logic pretty easily in a script tag using vanilla JavaScript, utilizing Web Components gives us the ability to encapsulate specific logic and functionality within the component, thus keeping our code more organized and understandable. This is the same reason we utilize component frameworks like Vue and React. Also, as we discussed earlier, Web Components are flexible in that they can be used without a JS framework, but are also compatible with modern frameworks (React and Vue both other support for using Web Components). Vue-Powered Web Components Vue 3.2 includes built-in support for defining custom Web Components while utilzing the Vue API. In this way, we get the best of both worlds - custom, reusable components across frameworks/interfaces, plus the excellent API of Vue. Let's take our example of getting the current time, and translate that into a Vue component. We will be using , which is the recommended way to write Vue single-file components today. To start, let's create our new file, CurrentTime.ce.vue (ce in this case stands for custom element). ` Great, our component is doing exactly what we were doing before. Next, we need to import this into our main Javascript somewhere, and define it as a custom element. ` What did we do here? 1. First, we import Vue's defineCustomElement function, which converts a Vue component into a custom element. 2. We then import our Vue SFC, and pass it into defineCustomElement, generating the constructor required for the web components APIs. 3. Then, we define the custom element in the DOM, supplying it with the tag that we want to use (current-time) and the constructor it should use to render. With that, our Vue web component can now be rendered in our app! And since web components work in all modern frameworks (as well as non-JS frameworks like Ruby on Rails or Laravel), we can now build out a suite of web components for our application using Vue, and then utlize them in any frontend we want. Here's a basic example using vanilla JS, and the default Vite template: ` You can see a working example of this on Stackblitz. More Features Creating a basic Vue component isn't always what you want to do, though. What happens if we need to utilize props or events? Fortunately, Vue has us covered here as well. Let's explore some of the basic functions we'd expect from our custom Vue components. Props The first thing we want to do is pass in props to our web component. Using our component, we want to be able to set the time zone. For this case, we can use props as we normally would for an HTML element. In our HTML template, let's change our code to the following: ` If you save your file now, you will probably get an error in your console like this one: ` This is because our prop isn't defined in the component yet. Let's take care of that now. Go back to your Vue component, and make the following changes: ` In our Vue component, we are now defining props (using Vue 3.2's defineProps helper, which we do not need to import), then using the timeZone prop to translate the date into the correct time zone string. Nice! Save your files, and our app should work again as expected, but this time, it will display the date in a different time zone. Feel free to play around with it a bit, trying out some different time zones. By default, Vue will translate props into their defined types. Since HTML only allows strings to be passed in as attributes, Vue is handling the translation to different types for us. Events From the docs: "Events emitted via this.$emit or setup emit are dispatched as native CustomEvents on the custom element. Additional event arguments (payload) will be exposed as an array on the CustomEvent object as its details property." Let's add a basic emit from our component that will trigger a console.log. In our Vue component, update our script block to the following: ` The main change we're making here is to add defineEmits (also available without import, similar to defineProps) in order to define what events this component makes. We then begin to use this in our setInterval step, to emit the new date as an event. In our main.js, we'll now add the event listener to our web component. ` With this, whenever the first component emits a datechange event, we will be able to listen for it, and act accordingly. Nice! Slots Slots are used exactly as expected within Vue, including named slots. Scoped slots, as they are an advanced feature within a full Vue application, are not supported. Also, when utilizing named slots in your application, you will need to use the native slot syntax, rather than Vue's specific slot syntax. Let's give this a try now. In you Vue component, change your template to the following: ` For this example, we are using a standard slot (we'll get back to named slots later). Now, in your HTML, add some text in between the tags: ` If you save and reload your page, you should now see that your text (or whatever content you want) is correctly passing into your web component. Now, let's do the same thing using named slots. Change your Vue component to have a named slot (`, for example), and your HTML like this: ` The result should be the same! And now we can use named slots in our web components. Styles One of the great parts about web components is that they can utilize a shadow root, an encapsulated portion of the DOM that contains their own styling information. This feature is available to our Vue web components as well. When you name your file with the .ce.vue extension, it defaults to having inline styles. This is perfect if you want to use your components as a library in an application. Provide/Inject Provide and inject also work as expected within Vue web components. One thing to keep in mind, however, is that they only can pass data to other Vue web components. From the docs, "a Vue-defined custom element won't be able to inject properties provided by a non-custom-element Vue component." Conclusion Vue 3.2 provides the ability to write custom web components using Vue's familiar syntax, and the flexibility of the Composition API. Keep in mind, however, that this is not the recommended approach to writing Vue applications, or application development in general. The documentation goes to great lengths to explain the differences between web components and Vue-specific components, and why the Vue team feels their approach is preferable for web development. However, web components are still an amazing technology for building cross-framework applications. Plenty of tools exist in the web development ecosystem focused purely on web components, such as Lit or Ionic. While this may not be the recommended approach to building applications with Vue, it can provide an encapsulated way to get certain features developed and functional across teams or projects. Regardless of your stance on web components, I highly encourage you to check out this new feature of Vue and experiment with it yourself. You could even try mounting your component in React or Svelte, and see how easy it is to work with across JavaScript frameworks. Most important of all, remember that the development ecosystem is always improving and growing, and it's up to you to be ready to grow with it. StackBlitz Demo Play around with the StackBlitz demo below and here's an example of a Vue web component I am utilizing in a side project I'm working on. Have fun!...

Oct 5, 2021

Auth for Frontend Devs with Chance Strickland cover image

Auth for Frontend Devs with Chance Strickland

Authentication serves as the foundation of data security, acting as the gatekeeper that verifies the identity of users accessing a system or application. In this JS Drops training by Chance Strickland, viewers will be introduced to high level auth concepts, tailored for frontend developers. Chance begins by discussing the traditional email/password authentication method, which is widely used but can be vulnerable to attacks like phishing. They emphasize the need for additional layers of security, such as two-factor authentication (2FA) and biometrics, to enhance the protection of sensitive data. By combining something the user knows (password), something they have (2FA device), and something they are (biometric data), the risk of unauthorized access is significantly reduced. The conversation then shifts towards OAuth and JSON Web Tokens (JWT), two popular authentication methods used in modern applications. OAuth allows users to grant limited access to their data to third-party applications without sharing their credentials. This method is commonly used by social media platforms and APIs. JWT, on the other hand, is a token-based authentication approach that securely stores user information in a JSON format. Chance highlights the challenges of token management, including the use of refresh tokens to extend the validity of access tokens and the importance of securely storing and transmitting these tokens. To ensure secure access control, Chance emphasizes the significance of building an authorizer, a component that verifies the permissions of users attempting to access certain resources. This helps prevent unauthorized access and ensures that only authenticated users with the appropriate privileges can perform specific actions. Chance also mentions the use of meta frameworks like Remix, which provide built-in authentication features, making it easier for developers to implement secure authentication systems. Understanding and implementing robust authentication methods is paramount in today's data-driven world. By combining traditional methods like email/password with additional layers of security like 2FA and biometrics, and leveraging modern approaches like OAuth and JWT, developers can create secure systems that protect sensitive data. Building a secure access control system and utilizing meta frameworks can further enhance the authentication process. With the right knowledge and tools, developers can ensure data security and provide users with a seamless and protected experience....

May 23, 2024

DEV Community

DEV Community

Waleed Asender

Posted on Oct 1, 2023 • Updated on Oct 12, 2023

Dynamic Refs in Vue3 The Right Way

Understanding refs.

Refs in Vue are a way to access and manipulate DOM elements or component instances. You may consider it as the Vue replacement for getElementById .

Instead of writing:

in Vue you will write:

then you can manipulate the element commentCard as you wish.

The Pitfall of Static Refs

Unfortunately, In many cases, static refs are bound to a specific element or component during initialization. This can become problematic when dealing with dynamic UIs where elements are created or removed based on dynamic fetched data.

Let's say we have a blog with comment list, and we want to reference each comment DOM, but this comment list is dynamic and we don't know how many comments will be there:

If we need for any reason to manipulate these elements or components it will be difficult to reference them using static Refs commentCard1 , commentCard2 , commentCard3 ..., we will need to bound the whole block with a parent Ref then call a function to refresh the list of child elements every time we want to interact with it, this will cause performance issues and may fail in some cases.

Instead of defining static Refs, we need to generate dynamic Refs for the element in the loop in as callback, and assign them to a Vue object variable using ' Function Refs ':

This means we'll collect the Ref of each created DOM element in the loop and store them in this object. This gives us easy access to all the DOMs, letting us change them using their assigned Ids:

Thanks for reading! I hope this method help you in your development work.

Top comments (0)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

dm8ry profile image

The ARRAY_TO_STRING() function in PostgreSQL

Dmitry Romanoff - May 14

furkangozukara profile image

Massive OpenAI Spring Update GPT-4o - Amazing New Features - All 22 Videos - RTX Super Res Upscaled

Furkan Gözükara - May 14

autotelico profile image

How to add a video into your website in Next.js 14

Henrique Magalhães - May 14

intersystemsdev profile image

Orchestrating Secure Management Access in InterSystems IRIS with AWS EKS and ALB

InterSystems Developer - May 14

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

别离开,为了更好的访问体验,请进行验证,通过后即可继续访问网页

vue ref assignment to constant variable

  • Skip to main content
  • Skip to search
  • Skip to select language
  • Sign up for free
  • Português (do Brasil)

TypeError: invalid assignment to const "x"

The JavaScript exception "invalid assignment to const" occurs when it was attempted to alter a constant value. JavaScript const declarations can't be re-assigned or redeclared.

What went wrong?

A constant is a value that cannot be altered by the program during normal execution. It cannot change through re-assignment, and it can't be redeclared. In JavaScript, constants are declared using the const keyword.

Invalid redeclaration

Assigning a value to the same constant name in the same block-scope will throw.

Fixing the error

There are multiple options to fix this error. Check what was intended to be achieved with the constant in question.

If you meant to declare another constant, pick another name and re-name. This constant name is already taken in this scope.

const, let or var?

Do not use const if you weren't meaning to declare a constant. Maybe you meant to declare a block-scoped variable with let or global variable with var .

Check if you are in the correct scope. Should this constant appear in this scope or was it meant to appear in a function, for example?

const and immutability

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. This means that you can't mutate the value stored in a variable:

But you can mutate the properties in a variable:

  • Documentation
  • Free Course

vue ref assignment to constant variable

Reactivity Tutorial for Vue 3 - Data and Component State for Beginners

written by ... Brian Driscoll | Date: March 24, 2023

What are reactive variables?

They are variables that, when changes occur, trigger a rerender so you can see the result of that change in the browser.

In Vue 3’s composition API, we have 2 ways to create reactive variables, by using ref or reactive . Having 2 ways to do this can often be confusing at first. Which one should you use and why? In this article, we explain how to use both and give you a framework for knowing when to use them.

What you will learn...

As always, you can watch the video, read the article, or use both!

Props from Parent to Child

Basic Rules for Using Ref

This is the first way to create reactive variables in your Vue application. A good rule of thumb when working with reactivity:

  • Always use ref unless you have a need to use reactive.

Ref is simple and straightforward and will allow you to accomplish a lot without confusing you.

Let’s start by creating a basic single page component:

We establish the variable title and give it the string value “Reactivity Explained”.

In the template we call the title variable using mustache syntax {{ }} . Run your application and Reactivity Explained will output to the screen.

Now we want to change this title while the program is running. We are going to add a button and a function called changeTitle .

The button has a click handler that calls the changeTitle method . In the changeTitle method, we change the value of title and log it to the console.

When you click the button, 2 things happen:

  • The title variable’s value changes as noted on the console but…
  • The title on the screen stays the same.

Props from Parent to Child

So why does the variable change but browser output stays the same?

There is no reactivity so when the variable changes, a rerender does not occur.

Let’s add some reactivity using ref!

We made 3 changes to add reactivity with ref:

  • Import ref from Vue.
  • Wrap the variable value with a ref and parentheses.
  • Change the value of the ref variable with .value syntax in the changeTitle function .

By wrapping the value with a ref, we tell Vue that this variable is reactive. To change a ref value, we have to call .value to access its contents. At first this maybe a little confusing, but there is a benefit to this syntax.

When using .value syntax, it makes it explicit that we are changing a reactive state value and triggering a rerender. Also notice how the template does not use the .value syntax. The template will automatically unwrap your ref value for you.

Now you will notice that the title on the browser changes whenever you click the button.

Conditionally Toggle Elements With Ref

Another great way to use ref variables is to conditionally render elements to the screen. In this case we are going to toggle elements.

To achieve this, we are going to use v-if statements (Vue) and a ternary operator (JavaScript):

In the template we have 2 <h1> tags. Inside them are two v-if directives. If the value in the v-if matches the ref variables value, then it will print out. You will notice we made one set to true and the other set to false.

The button is binded to the jump function. And the text within the button prints out based on the truthyness value of isInPool.

So when the jump function is called, it takes the value of isInPool and sets it to the opposite value. That means if isInPool is equal to true, set it to false, and vice versa.

When isInPool is true, the browser will print:

Props from Parent to Child

When isInPool is false:, the browser will print:

Props from Parent to Child

Ref is a great way to add reactivity and is very powerful. It is also explicit and makes it easy to understand what is going on within your template.

The one thing that may confuse people at first is the .value syntax. When running logic on your ref variables within the script, you will usually have to use this syntax. But there are cases where the .value syntax is not needed, such as when the ref value is in your template.

But for simplicity, use .value when using the ref value in your script and don’t use it within your template . There will be edge cases when this rule doesn’t apply, but you will learn that with experience.

Now we will talk about Vue 3’s other way for adding reactivity!

Basic Rules for Reactive

Reactive variables have some major differences from their ref counterpart:

  • Only accepts and object, unlike ref which can accept any data type
  • You cannot replace the object because it will lose reactivity
  • You can only change properties within a reactive variable to maintain reactivity

For example:

Notice that between the parentheses is an object and the object has properties with values.

Now let’s try to change the object:

This may seem like it would work, but unfortunately we would lose reactivity . We can’t replace the object. We can only change properties WITHIN the object.

Now that we have that out of the way, let’s start with some examples.

Print out a List With Reactive

So here we have a reactive object that contains an employee’s information. Let’s go ahead and print this out to our template using a v-for loop :

In our v-for loop , we ask for both the item and name of the property. To do this, we explicitly label name as our key and bind it.

What is happening exactly?

We are telling Vue that we want both the property names (name) and the property values (item) from the reactive object we are printing out. We also let Vue know that the name will be used as a key for identification.

Just like how in an array the key is the position: position 0, position 1, etc. In an object, instead of a position number, we establish position by using the property names. In this case: name, birthdate, salary, department, and position.

Now that we understand how the v-for loop is printing out the data, let’s relate this to a more real use case.

Using Reactive with Data

Let’s say we are trying to fetch data from a database. In this database, we have a list of employees. To make this simple for us, we are going to skip the whole fetching part as that is a different lesson.

Instead, we will write out an example object to represent data that we would fetch.

And after we have fetched this data, we will assign it to our reactive variable, employee.

So now we have a variable called allEmployees. We assign the first employee object to our reactive variable, employee.

The same information from Sheila will print out to the template.

Props from Parent to Child

What we want to do is switch this information to Bob.

First, add a button to the template so we can have something to click and call a method from.

Now let’s create the method changeEmployee . Someone new to Vue may try to change the information by changing the object:

There is a problem with this.

We are not allowed to reassign a whole entire new object to the reactive variable. This mutation gets rid of our reactivity. If you console log employee with this method, you will see that employee DOES change, but it does not trigger a rerender.

In Vue, reactive objects are meant to be changed via the properties . This is allowed:

Because we access the property, our reactive object maintains reactivity and you will see “Sheila” replaced by “Carella” in the template.

But, we want ALL of these properties to be changed to the 2nd employee’s information. That’s where JavaScript’s built-in object methods come in handy:

We tell Vue that we want to take the reactive object of employee and replace all the property values with the property values of allEmployees 1 .

And wallah, our new employee’s information prints out.

To make sure you understand EXACTLY what object.assign is doing, it is very similar to how this version works:

This for loop matches up the property names of each object and replaces the property value. The object version is much cleaner and easier to read, but they both achieve the same result.

One last thing!

To make sure you understand exactly how this works, remove a property from Bob:

We removed Bob’s position. Click the button to trigger changeEmployee and you get this result:

Props from Parent to Child

Notice how all of the properties still exist. The difference is that the position of “Social Media Manager” stays the same. We are merely changing property values, not replacing them.

Using Ref and Reactive to Manage a Component State

Now that have used both ref and reactive, we are going to apply both of these reactivity fundamentals to manage component state.

In this application, we will:

  • Use ref to track user input
  • Use reactive to handle component state
  • Use the value of the user input to decide on the component’s state

Let’s first create the basics of this application:

First, we create the input and use a directive called v-model. This directive connects the input to the userInput variable. We also have made the userInput variable a ref variable so that it is reactive. Now whatever we type into the input will automatically update the userInput variable.

Second, we create componentState using reactive. We set three state conditions: (1) inProgress, (2) error, (3) success. When the component mounts, it starts as in progress. Then, depending on the input, we will decide on the user state (which we have not done yet).

The last part are the p tags. We created 3 statements that will render to the page depending on the component’s state. Each one corresponds with either inProgress, error, or success.

Now we need to add a button and a method to create interactivity.

In the template:

In the script:

So now when we click the button, we validate the user’s input. It takes the userInput (updated using v-model), and uses an if-else statement to set 3 conditions:

  • success condition: the string length is longer than 2 characters in length
  • error condition: the string length is less then or equal to 2 AND greater than 0
  • inProgress condition: when component is mounted and any other condition

Let’s also add some CSS to make the validation text more prominent:

Depending on the user’s input, we will see text based on the component’s state. This is a great way to add form validation to your forms. All you have to do is adjust the submitForm method to the conditions you want to set.

Reactivity in Vue 3 can be confusing, but ref and reactive have different use cases which allow us to create powerful, interactive applications. Using ref for most cases makes it simple to add reactivity to your application. And reactive makes it easy to logically group state or data information within an object.

If you found the article helpful, go to our free-course page and sign up. We will be releasing a full fundamentals course on Vue 3 soon, 100% free!

Advisory boards aren’t only for executives. Join the LogRocket Content Advisory Board today →

LogRocket blog logo

  • Product Management
  • Solve User-Reported Issues
  • Find Issues Faster
  • Optimize Conversion and Adoption
  • Start Monitoring for Free

Understanding refs in Vue

vue ref assignment to constant variable

Editor’s note : This post was updated on 4 October 2022 to include information on watching ref s in Vue, as well as ensuring that all information reflects the most recent version of Vue.

Understanding Refs In Vue.js

In this tutorial, we’ll demonstrate how to reference HTML elements in your Vue.js components .

We’ll cover the following in detail:

What is Vue.js?

What are ref s in vue.js, getelementbyid in vue.js, how to use ref s in vue.js.

  • this.refs in Vue.js

How Vue.js ref s work

Displaying html elements in vue.js, displaying the html input value, displaying a vue element’s url, handling conditionals in vue.js, watching ref s in vue.

This Vue ref s tutorial is suited for all stages of developers who use Vue — including beginners. Here are a few prerequisites before you get started:

  • Node.js version 10.x or above. Verify your version by running node -v in your terminal/command prompt
  • npm 6.7 or above
  • A code editor; I highly recommend VS Code
  • Vue.js 3 installed globally on your machine
  • Vue CLI 3.0 installed on your machine. To do this, uninstall the old CLI version first with npm uninstall -g vue-cli , then install the new one using npm install -g @vue/cli
  • Download a Vue starter project
  • Unzip the downloaded project, navigate into it, and run npm install to keep all the dependencies up to date

Vue.js is a progressive JavaScript framework created by Evan You and the Vue core team with contributions from more than 230 community members. Vue is used in more than 870,000 projects and has more than 175,000 stars on GitHub .

Vue.js is an approachable core library that focuses only on the view layer. It also has a massive ecosystem of supporting libraries that help you easily build responsive web experiences.

Ref s are Vue.js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application.

If a ref attribute is added to an HTML element in your Vue template, you’ll then be able to reference that element or even a child element in your Vue instance. You can also access the DOM element directly; it is a read-only attribute and returns an object.

The use of JavaScript’s getElementById is not encouraged in Vue, as it creates performance issues. Vue’s ref helps you “reference” DOM elements in a more efficient way.

The ref attribute makes a DOM element selectable by serving as the key in the parent $ref attribute.

Putting a ref attribute in an input element, for instance, will expose the parent DOM node as this.$refs.input , or you can say this.refs["input"] .

For a quick visual guide on referencing with $refs in Vue.js, check out this video tutorial .

this.refs in Vue

You can manipulate a DOM element by defining methods on the element’s reference. For example, you could focus on an input element with this :

In this way, ref s can be used just like the document.querySelector('.element') in JavaScript or the $('.element') in jQuery. While document.querySelector() performs some of the functions of ref s, ref s are more efficient, because they give you direct access to the specific element you need. On the other hand, document.querySelector() simply returns the first element in your DOM that matches the selector you specified. The $refs can be accessed both inside the Vue.js instance and outside of it. However, they are not data properties, so they are not reactive.

On template inspection in your browser, $refs do not show up at all because it is not an HTML attribute; it is only a Vue template attribute.

If you followed this post from the start, you should have downloaded the starter project and opened it up on VS Code. Open the components folder and copy this into the test.vue file:

Now run this in your development server with the command:

You will see that the user interface displays a simple counter that gets updated on click, but when you open your developer tools in the browser, you will notice that it logs undefined.

It is very important that you get the syntax right because this means that Vue does not see this as an error, but it is. According to what we already know about Vue ref s, they return an object, but judging by the undefined response, something is wrong.

Copy the code below into the test.vue file:

When you run this and inspect it, you will notice that it now returns an object:

Inspecting Test.Vue

A quick look at the code block will reveal the correct syntax: inside the template, it is called ref , but when we refer to it in the Vue instance, it is called $refs . This is very important to note to not get an undefined returned. The syntax ref that’s used inside the template is an attribute given to an element. $refs on the other hand, is a collection of the elements in your application that have been given the ref attribute. You can access every single possible property of the referenced element, including the element as it is in the template.

Getting DOM elements in Vue.js

Let’s try logging some of the properties that might be of interest to us. Your test.vue file should be:

The application on your browser should look like this:

To display the HTML element as it is in the DOM, go into the submit method and change the methods code to the following:

The input here is the reference name you created earlier inside the element ( ref="input" ). It can be any name of your choice.

vue ref assignment to constant variable

Over 200k developers use LogRocket to create better digital experiences

vue ref assignment to constant variable

To display the HTML element input value — the string that was typed into the text box in the user interface — go into the submit method and change the code to:

This displays exactly the string you type in, which shows a similarity to query selection which vanilla JavaScript and jQuery can achieve too.

The webpage in which the element can be found is also one of the many things that can be displayed with the Vue ref . Go into the submit method and change the code to this:

There are many other things you can both access and log with the ref just from information on the returned object.

Vue.js refs can also be used inside elements that output more than one element in the DOM, like conditional statements where v-for directives are used. Instead of objects, ref s return an array of the items when called. To illustrate this, create a simple list like this:

When you run it again in the development server, it will look like this:

App Preview With Conditionals

Say you want to react to a change in a DOM element, like triggering a function when the value of an element changes. You can set up a watcher for this.

Below, we have a simple component with data:

We create the watcher inside the mounted hook so that it only takes effect after the component has been rendered. We use the $watch() instance method to watch for changes in the component’s data, myName . When the value changes, the console.log function is triggered.

You can find the full code of this tutorial on GitHub .

This post has exposed you to referencing HTML elements in your DOM in Vue.js. You can now both access and log these elements by all the element properties, including value, child node, data attributes, and even the base URL that houses it.

You have also been introduced to ways you can achieve this. It is important to note that ref s get populated after the Vue instance has initialized and the component has been rendered, so using ref s in computed properties is discouraged because it has the ability to directly manipulate child nodes. Happy hacking!

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket .

LogRocket Dashboard Free Trial Banner

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps — start monitoring for free .

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Facebook (Opens in new window)

vue ref assignment to constant variable

Stop guessing about your digital experience with LogRocket

Recent posts:.

Developing Web Extensions With Wxt

Developing web extensions with the WXT library

Browser extensions are an important part of the web ecosystem. They make our lives easier and enhance our web browsing […]

vue ref assignment to constant variable

Bulma CSS adoption guide: Overview, examples, and alternatives

Explore how Bulma CSS simplifies frontend development with its ease of use and customizable, responsive, pre-designed UI elements.

vue ref assignment to constant variable

Using Mountaineer to develop a React app with Python

Develop a React app with Python using the Mountaineer framework for building a simple app with integrated your frontend and backend database.

vue ref assignment to constant variable

Enhance CSS view transitions with Velvette

Velvette is a utility library developed to make working with view transitions easier.

vue ref assignment to constant variable

One Reply to "Understanding refs in Vue"

Leave a reply cancel reply.

  • ASP.NET Core
  • Entity Framework

3 different ways to access constants in a Vue template

  • by Karthik Chintala
  • December 19, 2019 February 9, 2020

different ways to access constants in vuejs featured image

In this post, I’ll show how to access a constant in the vue <template> tag.

If we consume the constant directly in the vue template we’ll get an error when compiling the app.

[Vue warn]: Property or method “NumberOne” is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.

Here’s the example code with the above error.

The above example may not compile at all because NumberOne is defined but we are not using it anywhere.

error: ‘NumberOne’ is assigned a value but never used

If you are using the constant anywhere in the file, then you shouldn’t see the above error.

Okay, let’s fix accessing constant in the vue template section.

Adding a reactive property in data() — Not the best

One way to silence this is to add a local property in the data and use the local variable in the template instead of directly accessing the constant.

This solves the problem, but we don’t need to have a reactive variable for a constant. ( Vue change detection caveat )

Under the hood, vue creates getter and setter for numberOne . So, numberOne variable will be reactive.

For simple use cases like the above example, I think it’s okay to go with this approach. But, I don’t personally recommend.

Create private variables in created() hook — GOOD

We’ll have to create a variable in the created hook and utilize the variable in the template.

This is simple to do.

And this doesn’t add the variables to the reactive system because when the created() hook is called Vue has already finished the observation phase .

Note : all Vue API/internal properties start with either $ or _, so as long as your property doesn’t use these two prefixes it will be totally fine.

If you have very limited usage, I think this is the best way to use constants in the template.

A plugin to access constants — GOOD

If you have many constants that should be accessed across the files, it’s better to create a plugin and access these.

In the main.js file, add the following lines to use the plugin across.

and finally in the file(s), we’ll call the function.

This is the best way of having the constants if you wish to use them all over your files.

If you have many files that use the common constants, it’s better to go with this approach.

  • creating private variables

Karthik Chintala

Karthik is a passionate Full Stack developer working primarily on .NET Core, microservices, distributed systems, VUE and JavaScript. He also loves NBA basketball so you might find some NBA examples in his posts and he owns this blog.

Related Posts:

How to read/write to computed properties?

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Save my name, email, and website in this browser for the next time I comment.

TypeError: Assignment to Constant Variable in JavaScript

avatar

Last updated: Mar 2, 2024 Reading time · 3 min

banner

# TypeError: Assignment to Constant Variable in JavaScript

The "Assignment to constant variable" error occurs when trying to reassign or redeclare a variable declared using the const keyword.

When a variable is declared using const , it cannot be reassigned or redeclared.

assignment to constant variable

Here is an example of how the error occurs.

type error assignment to constant variable

# Declare the variable using let instead of const

To solve the "TypeError: Assignment to constant variable" error, declare the variable using the let keyword instead of using const .

Variables declared using the let keyword can be reassigned.

We used the let keyword to declare the variable in the example.

Variables declared using let can be reassigned, as opposed to variables declared using const .

You can also use the var keyword in a similar way. However, using var in newer projects is discouraged.

# Pick a different name for the variable

Alternatively, you can declare a new variable using the const keyword and use a different name.

pick different name for the variable

We declared a variable with a different name to resolve the issue.

The two variables no longer clash, so the "assignment to constant" variable error is no longer raised.

# Declaring a const variable with the same name in a different scope

You can also declare a const variable with the same name in a different scope, e.g. in a function or an if block.

declaring const variable with the same name in different scope

The if statement and the function have different scopes, so we can declare a variable with the same name in all 3 scopes.

However, this prevents us from accessing the variable from the outer scope.

# The const keyword doesn't make objects immutable

Note that the const keyword prevents us from reassigning or redeclaring a variable, but it doesn't make objects or arrays immutable.

const keyword does not make objects immutable

We declared an obj variable using the const keyword. The variable stores an object.

Notice that we are able to directly change the value of the name property even though the variable was declared using const .

The behavior is the same when working with arrays.

Even though we declared the arr variable using the const keyword, we are able to directly change the values of the array elements.

The const keyword prevents us from reassigning the variable, but it doesn't make objects and arrays immutable.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

  • SyntaxError: Unterminated string constant in JavaScript
  • TypeError (intermediate value)(...) is not a function in JS

book cover

Borislav Hadzhiev

Web Developer

buy me a coffee

Copyright © 2024 Borislav Hadzhiev

vuemastery

Get 60% off a year of Vue Mastery courses

Reactivity in depth ​.

One of Vue’s most distinctive features is the unobtrusive reactivity system. Component state consists of reactive JavaScript objects. When you modify them, the view updates. It makes state management simple and intuitive, but it’s also important to understand how it works to avoid some common gotchas. In this section, we are going to dig into some of the lower-level details of Vue’s reactivity system.

What is Reactivity? ​

This term comes up in programming quite a bit these days, but what do people mean when they say it? Reactivity is a programming paradigm that allows us to adjust to changes in a declarative manner. The canonical example that people usually show, because it’s a great one, is an Excel spreadsheet:

Here cell A2 is defined via a formula of = A0 + A1 (you can click on A2 to view or edit the formula), so the spreadsheet gives us 3. No surprises there. But if you update A0 or A1, you'll notice that A2 automagically updates too.

JavaScript doesn’t usually work like this. If we were to write something comparable in JavaScript:

When we mutate A0 , A2 does not change automatically.

So how would we do this in JavaScript? First, in order to re-run the code that updates A2 , let's wrap it in a function:

Then, we need to define a few terms:

The update() function produces a side effect , or effect for short, because it modifies the state of the program.

A0 and A1 are considered dependencies of the effect, as their values are used to perform the effect. The effect is said to be a subscriber to its dependencies.

What we need is a magic function that can invoke update() (the effect ) whenever A0 or A1 (the dependencies ) change:

This whenDepsChange() function has the following tasks:

Track when a variable is read. E.g. when evaluating the expression A0 + A1 , both A0 and A1 are read.

If a variable is read when there is a currently running effect, make that effect a subscriber to that variable. E.g. because A0 and A1 are read when update() is being executed, update() becomes a subscriber to both A0 and A1 after the first call.

Detect when a variable is mutated. E.g. when A0 is assigned a new value, notify all its subscriber effects to re-run.

How Reactivity Works in Vue ​

We can't really track the reading and writing of local variables like in the example. There's just no mechanism for doing that in vanilla JavaScript. What we can do though, is intercept the reading and writing of object properties .

There are two ways of intercepting property access in JavaScript: getter / setters and Proxies . Vue 2 used getter / setters exclusively due to browser support limitations. In Vue 3, Proxies are used for reactive objects and getter / setters are used for refs. Here's some pseudo-code that illustrates how they work:

Code snippets here and below are meant to explain the core concepts in the simplest form possible, so many details are omitted, and edge cases ignored.

This explains a few limitations of reactive objects that we have discussed in the fundamentals section:

When you assign or destructure a reactive object's property to a local variable, accessing or assigning to that variable is non-reactive because it no longer triggers the get / set proxy traps on the source object. Note this "disconnect" only affects the variable binding - if the variable points to a non-primitive value such as an object, mutating the object would still be reactive.

The returned proxy from reactive() , although behaving just like the original, has a different identity if we compare it to the original using the === operator.

Inside track() , we check whether there is a currently running effect. If there is one, we lookup the subscriber effects (stored in a Set) for the property being tracked, and add the effect to the Set:

Effect subscriptions are stored in a global WeakMap<target, Map<key, Set<effect>>> data structure. If no subscribing effects Set was found for a property (tracked for the first time), it will be created. This is what the getSubscribersForProperty() function does, in short. For simplicity, we will skip its details.

Inside trigger() , we again lookup the subscriber effects for the property. But this time we invoke them instead:

Now let's circle back to the whenDepsChange() function:

It wraps the raw update function in an effect that sets itself as the current active effect before running the actual update. This enables track() calls during the update to locate the current active effect.

At this point, we have created an effect that automatically tracks its dependencies, and re-runs whenever a dependency changes. We call this a Reactive Effect .

Vue provides an API that allows you to create reactive effects: watchEffect() . In fact, you may have noticed that it works pretty similarly to the magical whenDepsChange() in the example. We can now rework the original example using actual Vue APIs:

Using a reactive effect to mutate a ref isn't the most interesting use case - in fact, using a computed property makes it more declarative:

Internally, computed manages its invalidation and re-computation using a reactive effect.

So what's an example of a common and useful reactive effect? Well, updating the DOM! We can implement simple "reactive rendering" like this:

In fact, this is pretty close to how a Vue component keeps the state and the DOM in sync - each component instance creates a reactive effect to render and update the DOM. Of course, Vue components use much more efficient ways to update the DOM than innerHTML . This is discussed in Rendering Mechanism .

The ref() , computed() and watchEffect() APIs are all part of the Composition API. If you have only been using Options API with Vue so far, you'll notice that Composition API is closer to how Vue's reactivity system works under the hood. In fact, in Vue 3 the Options API is implemented on top of the Composition API. All property access on the component instance ( this ) triggers getter / setters for reactivity tracking, and options like watch and computed invoke their Composition API equivalents internally.

Runtime vs. Compile-time Reactivity ​

Vue's reactivity system is primarily runtime-based: the tracking and triggering are all performed while the code is running directly in the browser. The pros of runtime reactivity are that it can work without a build step, and there are fewer edge cases. On the other hand, this makes it constrained by the syntax limitations of JavaScript, leading to the need of value containers like Vue refs.

Some frameworks, such as Svelte , choose to overcome such limitations by implementing reactivity during compilation. It analyzes and transforms the code in order to simulate reactivity. The compilation step allows the framework to alter the semantics of JavaScript itself - for example, implicitly injecting code that performs dependency analysis and effect triggering around access to locally defined variables. The downside is that such transforms require a build step, and altering JavaScript semantics is essentially creating a language that looks like JavaScript but compiles into something else.

The Vue team did explore this direction via an experimental feature called Reactivity Transform , but in the end we have decided that it would not be a good fit for the project due to the reasoning here .

Reactivity Debugging ​

It's great that Vue's reactivity system automatically tracks dependencies, but in some cases we may want to figure out exactly what is being tracked, or what is causing a component to re-render.

Component Debugging Hooks ​

We can debug what dependencies are used during a component's render and which dependency is triggering an update using the renderTracked onRenderTracked and renderTriggered onRenderTriggered lifecycle hooks. Both hooks will receive a debugger event which contains information on the dependency in question. It is recommended to place a debugger statement in the callbacks to interactively inspect the dependency:

Component debug hooks only work in development mode.

The debug event objects have the following type:

Computed Debugging ​

We can debug computed properties by passing computed() a second options object with onTrack and onTrigger callbacks:

  • onTrack will be called when a reactive property or ref is tracked as a dependency.
  • onTrigger will be called when the watcher callback is triggered by the mutation of a dependency.

Both callbacks will receive debugger events in the same format as component debug hooks:

onTrack and onTrigger computed options only work in development mode.

Watcher Debugging ​

Similar to computed() , watchers also support the onTrack and onTrigger options:

onTrack and onTrigger watcher options only work in development mode.

Integration with External State Systems ​

Vue's reactivity system works by deeply converting plain JavaScript objects into reactive proxies. The deep conversion can be unnecessary or sometimes unwanted when integrating with external state management systems (e.g. if an external solution also uses Proxies).

The general idea of integrating Vue's reactivity system with an external state management solution is to hold the external state in a shallowRef . A shallow ref is only reactive when its .value property is accessed - the inner value is left intact. When the external state changes, replace the ref value to trigger updates.

Immutable Data ​

If you are implementing an undo / redo feature, you likely want to take a snapshot of the application's state on every user edit. However, Vue's mutable reactivity system isn't best suited for this if the state tree is large, because serializing the entire state object on every update can be expensive in terms of both CPU and memory costs.

Immutable data structures solve this by never mutating the state objects - instead, it creates new objects that share the same, unchanged parts with old ones. There are different ways of using immutable data in JavaScript, but we recommend using Immer with Vue because it allows you to use immutable data while keeping the more ergonomic, mutable syntax.

We can integrate Immer with Vue via a simple composable:

Try it in the Playground

State Machines ​

State Machine is a model for describing all the possible states an application can be in, and all the possible ways it can transition from one state to another. While it may be overkill for simple components, it can help make complex state flows more robust and manageable.

One of the most popular state machine implementations in JavaScript is XState . Here's a composable that integrates with it:

RxJS is a library for working with asynchronous event streams. The VueUse library provides the @vueuse/rxjs add-on for connecting RxJS streams with Vue's reactivity system.

Connection to Signals ​

Quite a few other frameworks have introduced reactivity primitives similar to refs from Vue's Composition API, under the term "signals":

  • Solid Signals
  • Angular Signals
  • Preact Signals
  • Qwik Signals

Fundamentally, signals are the same kind of reactivity primitive as Vue refs. It's a value container that provides dependency tracking on access, and side-effect triggering on mutation. This reactivity-primitive-based paradigm isn't a particularly new concept in the frontend world: it dates back to implementations like Knockout observables and Meteor Tracker from more than a decade ago. Vue Options API and the React state management library MobX are also based on the same principles, but hide the primitives behind object properties.

Although not a necessary trait for something to qualify as signals, today the concept is often discussed alongside the rendering model where updates are performed through fine-grained subscriptions. Due to the use of Virtual DOM, Vue currently relies on compilers to achieve similar optimizations . However, we are also exploring a new Solid-inspired compilation strategy, called Vapor Mode , that does not rely on Virtual DOM and takes more advantage of Vue's built-in reactivity system.

API Design Trade-Offs ​

The design of Preact and Qwik's signals are very similar to Vue's shallowRef : all three provide a mutable interface via the .value property. We will focus the discussion on Solid and Angular signals.

Solid Signals ​

Solid's createSignal() API design emphasizes read / write segregation. Signals are exposed as a read-only getter and a separate setter:

Notice how the count signal can be passed down without the setter. This ensures that the state can never be mutated unless the setter is also explicitly exposed. Whether this safety guarantee justifies the more verbose syntax could be subject to the requirement of the project and personal taste - but in case you prefer this API style, you can easily replicate it in Vue:

Angular Signals ​

Angular is undergoing some fundamental changes by foregoing dirty-checking and introducing its own implementation of a reactivity primitive. The Angular Signal API looks like this:

Again, we can easily replicate the API in Vue:

Compared to Vue refs, Solid and Angular's getter-based API style provide some interesting trade-offs when used in Vue components:

  • () is slightly less verbose than .value , but updating the value is more verbose.
  • There is no ref-unwrapping: accessing values always require () . This makes value access consistent everywhere. This also means you can pass raw signals down as component props.

Whether these API styles suit you is to some extent subjective. Our goal here is to demonstrate the underlying similarity and trade-offs between these different API designs. We also want to show that Vue is flexible: you are not really locked into the existing APIs. Should it be necessary, you can create your own reactivity primitive API to suit more specific needs.

Edit this page on GitHub

IMAGES

  1. When to Use Ref vs. Reactive // Vue Tips

    vue ref assignment to constant variable

  2. Ref vs. Reactive: What to Choose Using Vue 3 Composition API?

    vue ref assignment to constant variable

  3. How to Fix Uncaught TypeError: Assignment to constant variable

    vue ref assignment to constant variable

  4. vue3.2关于“TypeError: Assignment to constant variable”的问题解决方案_assignment

    vue ref assignment to constant variable

  5. Mastering Vue refs: From Zero to Hero

    vue ref assignment to constant variable

  6. vue3.2关于“TypeError: Assignment to constant variable”的问题解决方案_assignment

    vue ref assignment to constant variable

VIDEO

  1. Windblown Drizzles

  2. How Old The Beatles Were During Get Back Sessions

  3. Battlefield Hardline GRAY HAT SYNDICATE and Point of Interest Coins

  4. RenWeb Desktop Gradebook Setup

  5. How to platformer by thearmyants 100% (Platformer Demon) || GD 2.2

  6. Climate Change and Boundary Conditions

COMMENTS

  1. TypeError: Assignment to constant variable

    This behavior ensures that the variable remains constant throughout its scope. To fix this error, consider using the let keyword instead of const if you need to update the variable's value. Alternatively, ensure that you are not attempting to reassign the constant variable inadvertently.

  2. Reactivity with the Vue 3 Composition API: ref() and reactive()

    Vue reactive() We can use reactive( ) to declare state for objects or arrays in Vue using the Composition API: import { reactive } from 'vue' const state = reactive({ first_name: "John", last_name: "Doe", }) In the code snippet above, we declare to Vue that we want to track the object in the reactive( ) function.

  3. Template Refs

    ref is a special attribute, similar to the key attribute discussed in the v-for chapter. It allows us to obtain a direct reference to a specific DOM element or child component instance after it's mounted. This may be useful when you want to, for example, programmatically focus an input on component mount, or initialize a 3rd party library on an element.

  4. Reactivity Fundamentals

    Limitations of reactive() . The reactive() API has a few limitations:. Limited value types: it only works for object types (objects, arrays, and collection types such as Map and Set).It cannot hold primitive types such as string, number or boolean.. Cannot replace entire object: since Vue's reactivity tracking works over property access, we must always keep the same reference to the reactive ...

  5. Mastering Vue refs: From Zero to Hero

    Open the demo. ref({ name: 'Batman' }) creates a ref that stores an object. You can access the object from the ref using hero.value.And also access any properties of that object using regular property accessors: hero.value.name. Moreover, the object stored in a ref automagically becomes reactive!Plus the reactivity is applied deeply on nested objects or arrays.

  6. Vue 3 Composition API

    Now let's look at the same example as above, using the Composition API. First, we'll take a look at ref. From the Vue 3 documentation: ref takes an inner value and returns a reactive and mutable ref object. The ref object has a single property .value that points to the inner value. Below is our example code using ref:

  7. Reactivity Transform

    Note that if x is already a ref, toRef(__temp, 'x') will simply return it as-is and no additional ref will be created. If a destructured value is not a ref (e.g. a function), it will still work - the value will be wrapped in a ref so the rest of the code works as expected.

  8. Dynamic Refs in Vue3 The Right Way

    Solution. Instead of defining static Refs, we need to generate dynamic Refs for the element in the loop in as callback, and assign them to a Vue object variable using ' Function Refs ': This means we'll collect the Ref of each created DOM element in the loop and store them in this object. This gives us easy access to all the DOMs, letting us ...

  9. vue3中reactive变量不能赋值的问题:const a=ref(true); a=false报错?

    本人刚接触前端,属于用到什么学什么的那种,所以基础不是很牢。今天开发中遇到了这个问题,实在搞不懂,前来咨询各位大佬。在quasar+vue3项目下,控制台报错TypeError: Assignment to constant variable.

  10. TypeError: invalid assignment to const "x"

    The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. This means that you can't mutate the value stored in a variable: js.

  11. vue.js

    A VueJS project: I have a form object, where each property is bind with a corresponding form input. The object inside of the components looks like: export default { data () { return { ...

  12. Reactivity Tutorial for Vue 3

    We made 3 changes to add reactivity with ref: Import ref from Vue. Wrap the variable value with a ref and parentheses. Change the value of the ref variable with .value syntax in the changeTitle function. By wrapping the value with a ref, we tell Vue that this variable is reactive. To change a ref value, we have to call .value to access its ...

  13. Understanding refs in Vue

    Refs are Vue.js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application. If a ref attribute is added to an HTML element in your Vue template, you'll then be able to reference that element or even a child element in your Vue instance. You can also access the ...

  14. vue.js

    You can always define a variable outside of the Vue app scope and use it throughout the application. ... An example for that can be found below. //const.js export default { c1: 'Constant 1', c2: 'Constant 2' } // component.vue import const from './const'; export default { methods: { method() { return const.c1; } } } Share. Improve this answer.

  15. Reactivity API: Core

    Details. The ref object is mutable - i.e. you can assign new values to .value.It is also reactive - i.e. any read operations to .value are tracked, and write operations will trigger associated effects.. If an object is assigned as a ref's value, the object is made deeply reactive with reactive().This also means if the object contains nested refs, they will be deeply unwrapped.

  16. 3 different ways to access constants in a Vue template

    This solves the problem, but we don't need to have a reactive variable for a constant. (Vue change detection caveat) Under the hood, vue creates getter and setter for numberOne. So, numberOne variable will be reactive. For simple use cases like the above example, I think it's okay to go with this approach. But, I don't personally recommend.

  17. TypeError: Assignment to Constant Variable in JavaScript

    To solve the "TypeError: Assignment to constant variable" error, declare the variable using the let keyword instead of using const. Variables declared using the let keyword can be reassigned. The code for this article is available on GitHub. We used the let keyword to declare the variable in the example. Variables declared using let can be ...

  18. node.js

    Assignment to constant variable. Ask Question Asked 5 years, 5 months ago. Modified 21 days ago. Viewed 95k times 11 I try to read the user input and send it as a email. But when I run this code it gives me this error: Assignment to constant variable. var mail= require ...

  19. Component v-model

    The value returned by defineModel() is a ref. It can be accessed and mutated like any other ref, except that it acts as a two-way binding between a parent value and a local one: Its .value is synced with the value bound by the parent v-model; When it is mutated by the child, it causes the parent bound value to be updated as well.

  20. Why plain constant still works in Composition API (Vue 3)?

    2) You're updating ref and static. The other issue is that you're updating the static value followed by the ref. Changing ref will re-trigger rendering, at which point the static value would have changed. so if you remove the update through store, you should not be seeing the update happening any more. methods: {.

  21. Reactivity in Depth

    Vue's reactivity system works by deeply converting plain JavaScript objects into reactive proxies. The deep conversion can be unnecessary or sometimes unwanted when integrating with external state management systems (e.g. if an external solution also uses Proxies). The general idea of integrating Vue's reactivity system with an external state ...