Intro to reactiveUtils

Intro to reactiveUtils

Rene Rubalcava | May 23, 2022

Reactive at heart

If you weren't already aware, the ArcGIS API for JavaScript is reactive at heart. Since it's release, you have had the capability to watch for property changes. This provides a lot more flexibility for developers to watch for changes they care about. Rather than rely on a variety of events, you can just watch for particular properties to change.

Since the release of version 4 of the API, there has been a watchUtils you could use to help you watch for changes. The drawback is that depending on what you were interested in, you could use a utility to check when a property has been defined, changed, or is a true/false boolean value. These watchUtils are being deprecated in favor of reactiveUtils, so there is no time to update like today!


A core benefit to using reactiveUtils is the flexibility you have to manage property changes. Combine this with optional chaining, and you don't even need to check if properties exist up front.

Let's take a quick look at reactiveUtils and what they are used for.

  • on() - Listen for events on a target
  • once() - Like watch, but only fires one time as a Promise
  • watch() - Most versatile of the methods, used for watching property changes
  • when() - Similar to watch, but executes the callback when the expression returns truthy
  • whenOnce() - Executes the when expression only once as a Promise

This is an older example of how you might do some deep property watching compared to how you can use reactiveUtils.

// old watchUtils
watch(view, 'map.basemap.title', (title) => console.log(title));

// reactiveUtils
    () =>,
    (title) => console.log(title)

This sample isn't too exciting, but it gives you an idea of what you can accomplish.

An incredibly useful property to track is view.updating. This property will be true when there is data being fetched, and rendered by the map, it becomes false when that rendering is done. It's useful to know when the View, in 2d or 3d, has completed drawing.

    () => !view.updating,
    (updating) => /** take screenshot, notify user, etc **/

You can also watch for multiple properties to change. Maybe you are interested in checking when the zoom or scale of the map changes, but not when you pan the map. This requires that track the previous zoom value to compare.

let prevZoom;

// wait for view to be ready
whenOnce(() => view.ready).then(() => {
  // save the initial value
  prevZoom = view.zoom;
    () => [view.zoom, view.stationary],
    ([zoom, stationary]) => {
      // do not execute if values are the same
      if (zoom === prevZoom) return;
      // make sure view is stationary
      if (stationary) {
        // update tracked value
        prevZoom = zoom;
        // do something when the value is updated as expected

In this sample, as a bonus, we can look at an alternative to view.when() to check then the view.ready property is true using whenOnce.

You can get as detailed or specific in how you watch for property changes as needed. There's a great sample in the documentation you can look at with some good use cases.


An alternative to target.on() is using the on() to listen for events.

    () => view.popup,
    (event) => handleTriggerAction(event)

You can even listen for multiple events.

    () => view,
    ["click", "double-click"],
    (event) => handleViewEvents(event)

This could be useful if you want to handle multiple events the same way on a component or element.


This was just a quick intro to reactiveUtils in the ArcGIS API for JavaScript. There are many different use cases you can leverage in your applications with this utility. There are less methods in reactiveUtils than you would find in watchUtils, but now you have more flexibility in how you compose what is being watched, when you handle those updates and other side effects in your application. If you can learn how to leverage reactiveUtils in the ArcGIS API for JavaScript, you can take your development experience to the next level!

You can see more details in the video below!