A novel way of resetting state with Vue composition API

jorge florian
5 min readSep 26, 2020

Reset features are widespread in web applications. Therefore it’s worth finding a reusable solution without falling into complications.

Problem description

Let’s suppose you are a person that wants to start writing small blogs about technology, like me. But instead of using an existing platform, you want to create your own. And you want to have a web form that allows you to send invitations to your friends so they can follow up on your blogs. Kind of like this:

Example of Form to send invitations to friends

As we can see, the form has some fields about the person we want to invite and some notifications preferences. Additionally, there are some default values assigned: Frequency of notification is two weeks by default, and the notifications of Frontend and Backend content are enabled by default (let’s be honest, most of your friends are developers). To track the information of the form, we need to define reactive properties for each of the fields in the form.

In the previous code, we defined some ref and reactive values bound to the form fields, and additionally, we defined a callback used when the form is submitted. The callback unwraps the values and calls a function service with the data the user entered — nothing fancy here, just a common way of creating a form and saving the information. Let’s see it in action.

As you can see, our form kind of works; however, there is one last step missing, and probably you also noticed. After we send the invitation, the form still contains the data we recently submit or in other words, the component does not reset to its initial state. These kinds of reset features are widespread in web applications. Usually, with forms intended to be used multiple times, for instance, a Form that adds new users to a table or even on Dialogs that contains a form expected to have a clean state every time the dialog opens. Therefore it’s worth finding a general solution that allows us to reset component’s states without falling into complications.

Let’s briefly see the existing solutions and their disadvantages.

Existing solutions and their disadvantages

Imperative approach

The imperative approach involves manually reset every single value to its initial state.

The first problem of this approach is the manual process involved in resetting the sate. The developer always needs to remember to include a reset statement every time it adds a new field to the form. The second problem is the duplication of the default values, which need to be both in the instantiation of the reactive values and in the reset function; this last kind of dependency is known as Connascence of Value. We could avoid the second problem by removing the default values in the instantiation of the variables and call the resetState function afterward, but it would lose the implicit meaning of initial values, which are supposed to be defined with the instantiation of variables.

Destroy and create the component

This approach implies to recreate the component from scratch with the special “key" attribute which Vue's virtual DOM algorithm uses it to identify VNodes when diffing the new list of nodes against the old list. In a few words, the "key" attribute is kind of an Id for VNodes, which mean if we change it from, let's say, an initial value key="1"to key="2", Vue will identify the component with key="2" as a completely new element that appears, since it does not find a VNode with an Id equals to 2, and since the new VNodes list does not have an element with key="1" it infers it has to remove the DOM element of the current element with key="1". It's deletion and recreation in a nutshell.

Since the definition of the “key” attribute needs to be set by the parent component, which renders the component we want to recreate, this approach implies parent-child communication throw events.

The apparent downside of this approach is the need to involves the parent component to achieve the goal, especially if the developer wants to treat the form as an uncontrolled component. On the other side, if you’re going to treat the form as a controlled component, you have to lift the state to the parent component, and then we will still have the same problem but in the parent. Lifting the state translate the problem from one component to another.

A novel solution

We can create a function, or composition function, that contains the logic to reset any state of a component regardless of its shape and values. And since it’s just a function, we can easily reuse it in any component without changing its underlying logic. It’s just “Plug and Play.”

The above file exports a composition function. This function can receive any single argument that contains reactive or ref instances and recursively find them. Every reactive and ref instance that finds, it will add it to a list along with the value that contains at that exact moment. As a final step, it returns a callback that iterates over the list of reactive and ref instances and assigns back its corresponded initial value. Let’s see how we can use this function in our component.

As I said before, it’s just “Plug and Plays’, kind of it has to be for any piece of software intended to be reusable. I didn’t have to change the current implementation of components whatsoever, and the best part is that it is fully reusable along with any component. You can pass any nested object or arrays, and it will track any reactive/ref instance so it can reset its value afterward.

The composition API opens the gate to a new way of creating reusable pieces of logical concerns, and though it’s not a novel idea, indeed, it’s worth mentioning the fantastic job the Vue team just gave us. I encourage you to use this composition function and create others that have not been think of yet.

Codesanbox link with code examples.

--

--