DEV Community

Danny Blue
Danny Blue

Posted on

Monitoring State changes with the Proxy API

The idea of "state" is something that every developer will have to deal with at some point or another. For the sake of this article, we will define state as "data that represents our application". So, for a simple "counter" application, our state will be equally as simple.

const state = {
  counter: 0
};
Enter fullscreen mode Exit fullscreen mode

An object with one property that keeps track of our counter. See? Simple.
Now we will set up a simple UI to go with with our simple state for our simple app.

const el = document.createElement('h1'); // It's a big counter
document.body.appendChild(el);

const state = {
  counter: 0
};

const updateView = (state) => {
  el.innerHTML = state.counter;
}

updateView(state);
Enter fullscreen mode Exit fullscreen mode

PERFECT! But now a new requirement comes in and we need to update the UI with the new counter value every second. We can do that!

const el = document.createElement('h1'); // It's a big counter
document.body.appendChild(el);

const state = {
  counter: 0
}

const updateView = (state) => {
  el.innerHTML = state.counter;
}

updateView(state);

setInterval(() => {
  state.counter++
}, 1000)
Enter fullscreen mode Exit fullscreen mode

Now, we are updating our state but we need to update our UI along with it. The easiest way would be to just set innerHTML again, but that wouldn't be any fun. What we want to do is update innerHTML any time that the state changes, whether that be from our setInterval or from some other future update. Luckily, modern JavaScript has our back with the Proxy API. The Proxy API will allow us to monitor interactions with our state object. The below will behave exactly the same as our plain javascript object:

const el = document.createElement('h1'); // It's a big counter
document.body.appendChild(el);

const state = new Proxy({ counter: 0 }, {});

const updateView = (state) => {
  el.innerHTML = state.counter;
}

updateView(state);

setInterval(() => {
  state.counter++
}, 1000);
Enter fullscreen mode Exit fullscreen mode

I highly recommend you read through the MDN docs for Proxy but we will be focused on the set method. The set method will be called any time a property is set on our object. I can hear your wheels turning. "If we know when things are changed we can do stuff", I hear you shouting, and you would be correct!

const el = document.createElement('h1'); // It's a big counter
document.body.appendChild(el);

const state = new Proxy({ counter: 0 }, {
  set(target, prop, value) {
    target[prop] = value; // be sure to assign the new value.

    updateView(state);

    return true;
  }
});

const updateView = (state) => {
  el.innerHTML = state.counter;
}

updateView(state);

setInterval(() => {
  state.counter++
}, 1000);
Enter fullscreen mode Exit fullscreen mode

With our fancy new Proxy we don't need to worry about where, or how, our state was changed. We only need worry about the fact that it changed. This will also continue to work as we add more properties to our state object and it will also work with arrays.

Now we know how we can use the Proxy API to create and react to state changing in our application without any additional libraries or complicated logic. Let me know what you think! Can you think of any other cool uses for Proxy?

Top comments (0)