Reactivity in View Libraries - React & Vue

Implementation details of Reactivity in view libraries

Reactivity in View Libraries - React & Vue

Introduction

Most of the articles on the features of view libraries talk about the “what” part of it such as its syntax, learning curve, and best practices from a development perspective.

This article is not going to fall under the same category instead, it explains one of the key expectations of a declarative language or view library which is Reactivity.

Let us see “by how” reactivity is achieved in popular view libraries Vue and React.
Though from the usage point of view, it may look like each JS framework has its way of feature implementation for the Single Page Application approach, behind the scenes all such features are based on Vanilla JS and its experimental features.

Let’s dive into the implementation details to know how the JS features are elevated to fulfill the Reactivity mechanism.

Why Reactivity and why not any other core concepts?

The principles behind other core building blocks of React and Vue like Templating, Composition of components, DOM manipulation strategies (using Virtual DOM) are more or less similar.

Supporting blocks like Routing, State Management are also not focused on this article since those are either provided as secondary support from the library or a 3rd party library is used for that purpose as a de facto standard.

Reactivity

In general, Reactivity is a mechanism that maintains the sync between 2 related layers. Typically, this is achieved by watching for changes, emitting the events on mutation, and running the sync operations.

In web development, Reactivity is how the state and its behavior (Model) sync with the DOM (View) during mutations.

JavaScript is not reactive (at least not available as a built-in feature) i.e., when the state gets a new value, the logic and the view depends on it won't get recomputed automatically. It's the responsibility of the framework and/or developer to make sure both model and view are in sync.

Reactivity in Vue

VueJS uses the native Proxy API (available from ES6) to hook into the calls on data objects for adding custom behavior.
Let’s first take a glance at how this Proxy API works.

Proxy API

It is simply a wrapper around JS object where it can receive messages like target object, provided it has support to trap the operations over the object properties via the handler.
Without a handler, sending messages to proxy objects behaves identically to the original object.

Proxy API

As depicted in the above diagram, a handler can hook into the operations over the target properties such as read, write, etc.

We can add the tracking mechanism by intercepting the getter and setter functions via proxy handlers.

  • “get” function inside the handler would be called on while “reading” a property

  • “set” would be called on “write” action on the property

In Vue, the goal of reactivity is collecting the dependencies list (model) for every side effect (a function that uses the data model) and to recall all the side effects when the respective data gets mutated.

Proxy API Snippet
Handler: get (Track)Handler: set (Trigger)UI
A place to add the property to the dependency list against the current effect (a function that read this property)A place to re-rerun all the effects that use the updated propertyTemplates are maintained as nodes in Vue so it can also be treated as a data model, and it is preserved as an effect. This will be re-rendered if any of its properties gets mutated.

Reactivity in React

React doesn’t have any inbuilt mechanism for COMPLETE reactivity in action such as observe/track the changes in the data model and thereby updating the behavior and view itself. So, we can say React is not Reactive!

The developer should explicitly call state mutation calls to make it sync with the view. If any side effects need to be run, that must be wrapped in useEffect hook. All the side effects get a chance to run on whenever the component renders. Side effects with any dependency will run only if the dependency has any new value compared to the previous one.

All state update requests within an effect, event handlers are batched, and React may update it in a single go asynchronously.

Let’s see this through an example

Hook Snippet

As you can see, the data model can’t be mutated directly. i.e., this statement is not effective in React // someState = newValue
Either setState (for class components) -or- state update functions from useState/useReducer hook must be used to submit the update request to React. If there are any dependent computations, that should be wrapped as a side effect.

Summary

To summarize, let us define the type of reactivity in Vue and React.

Push

In Vue, the library itself takes care of tracking the dependencies and keeps the model and view in sync. It follows the track and trigger mechanism. This type is being called “PUSH” because we are not explicitly data tracking and forcing the re-rendering on data mutation. When there is a mutation, respective view changes are pushed automatically.

Pull

Technically, the state update calls are requests to React. Such request calls are scheduled, and they may not happen immediately. The control is with React and it will decide when to PULL the changes to update the DOM. Keeping the rendering control with itself, React can defer, prioritize, batch up the state update requests for better performance.


reactjs
vuejs
reactivity
proxy api
javascript
view libraries
spa
side effects
front end
state updates

By Balaji Rajendran
October 30, 2021

Talk to us for more insights

What more? Your business success story is right next here. We're just a ping away. Let's get connected.