Cookies Psst! Do you accept cookies?

We use cookies to enhance and personalise your experience.
Please accept our cookies. Checkout our Cookie Policy for more information.

Vue reactivity for impatient devs

In Vue it's all about managing the state of components. Modifying the State forces the UI to rebuild with the new data. But then, what is this so-called State?

App = State + UI

We can understand the UI as a printer that produces one T-shirt after another non-stop. The printer doesn't know:

  • Which T-shirt was printed before.
  • Who will sell
  • The theme.

An image of a old print house

💡 In summary: The printer only focuses on blindly printing T-shirts without remembering.

The client that orders the printer to print is the State. When they want a new batch of T-shirts, they just change the form data.

=== Form ===
Color: Red
Size: XL
Design: DonutAscii.svg

In Vue and many graphical libraries, something similar happens. There's a set of important variables that must be remembered while the app is running, which is the state that can also be seen as a form:

=== STATE ===
Username: smaugthur
Password: 1234
Games Won: 3
Game Finished: false
PositionX: 0
PositionY: -500

The UI, like the T-shirt printer, has a blank template that it needs to fill with the data requested by the client. When it receives the State data, we have a screen like this:

A videogame UI

💡 Any change in the state will force the UI to print a new image with the updated data.

However, the UI can also receive commands from the user to modify the State. A simple click on "Activate Dark Mode" will change the internal state, which in turn will force the UI to reprint a new screen. It's a cycle where...

💡 The state modifies the UI, and the UI modifies the state.

What was the point of understanding this?

The UI isn't intelligent 🧠, if nobody tells it, it can't know that the state has changed. That's why there have to be explicit ways to say, "Hey, the state changed, get to work!" This mechanism of making the UI react when the state changes is called Reactive States.

Now we're going to talk about the most important ways in Vue to achieve these reactive states, and we'll start by understanding how Vue handles these mechanisms Under the hood.

Fundamentals of Reactivity in Vue

In Vue, the state is represented by variables. JavaScript doesn't have internal mechanisms to observe changes in a variable and react to them. However, it does offer Proxies, which are effectively intermediary objects between the client and the actual variable.

💡 Proxy objects hold the actual value inside them and act as guards that decide what, how, and when the value of the real variable should be modified.

Vue wraps all state variables in Proxies, so now it has control over all the changes happening in the variables, giving it knowledge of when to rebuild the UI.

💡 Vue strongly recommends working with Proxy versions of the state.
Vue offers the following methods to wrap variables inside a Proxy and manage their state:

reactive()

It's a function that takes an object and creates a Proxy with the same data as the original object. Although it works the same as the original object, it is completely independent. Some important considerations:

  • Any changes to the Proxy object will not modify the original nor vice versa because THEY ARE DIFFERENT OBJECTS.
  • It performs a deep transformation. That means if there are nested objects, it will also convert them to their Proxy equivalent. This will cause any changes in the child properties to also trigger a state change.
  • It's not intended for use with primitive types (String, boolean, int...).
import { reactive } from 'vue'

const state = reactive({ count: 0 })
<button @click="state.count++">
  {{ state.count }}
</button>

ref()

It's another function that constructs proxies, but unlike reactive(), it's intended to handle both primitive types and objects. It works very simply. If it encounters a primitive, it simply creates a Proxy wrapping the value, and if it encounters an object, it executes a reactive() to obtain its Proxy version.

Considerations:

  • Like reactive, objects produced by ref() are independent of their originals.
  • It performs a deep transformation.
  • To access the wrapped value of a ref() Proxy, you call the proxy.value property. This is not the case with reactive, where you can directly access the properties.
import { ref } from 'vue'

const count = ref(0)

console.log(count) // { value: 0 }
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

And thats it, happy coding. Here some other useful resources:

Last Stories

What's your thoughts?

Please Register or Login to your account to be able to submit your comment.