Detect object changes with JavaScript Proxy

Detect object changes with JavaScript Proxy

Chris Bongers
Β·Jul 10, 2022Β·

3 min read

Play this article

Let's say we have an object for our users. How can we detect when a property changes?

const user = {
  firstName: 'Chris',
  lastName: 'Bongers',
  age: 10,
};

Now the user changes his age by using the following code.

user.age = 33;

However, we want to log this change to keep track of specific changes.

Using JavaScript Proxy to detect object changes

That's again where the Proxy object comes in handy. As we learned in the previous article, the Proxy object comes with a set handler (trap).

The set handler can pass us the following three parameters.

  • object: The whole object we are trying to modify
  • property: The property we are trying to modify
  • value: The new value we are trying to set

Let's create a proxy to our user object so we can attach a handler.

const handler = {
  set(target, prop, value) {
    // Our code
  },
};

const proxyUser = new Proxy(user, handler);

As for the code, we want to log which property is being changed, what the previous value was, and what the new value will be.

Then we need to ensure that we set the new value.

The result is the following function.

const handler = {
  set(target, prop, value) {
    console.log(`changed ${prop} from ${target[prop]} to ${value}`);
    target[prop] = value;
  },
};

Let's try it out by modifying the age again.

proxyUser.age = 33;

Now the console will show this change and log changed age from 10 to 33.

Detecting additional Object properties

Sometimes we might push new properties to the object. Let's see how we can capture that.

proxyUser.email = 'info@daily-dev-tips.com';

And again, this will neatly log the change: changed email from undefined to info@daily-dev-tips.com.

However, there is one small exception.

If we have a sub-object or array in our main object, it won't work out of the box.

const user = {
  firstName: 'Chris',
  lastName: 'Bongers',
  age: 10,
  address: {
    postalCode: '1234AB',
  },
};

proxyUser.address.postalCode = '5678CD';

This now logs nothing new, but the property is changed! And that's because there is now a deep proxy set.

To log on that level, we can again leverage the get handler and proxy each property to be a proxy itself 🀯.

const handler = {
  get(target, key) {
    if (typeof target[key] === 'object' && target[key] !== null) {
      return new Proxy(target[key], handler);
    }
    return target[key];
  },
  set(target, prop, value) {
    console.log(`changed ${prop} from ${target[prop]} to ${value}`);
    target[prop] = value;
  },
};

And now, when we rerun our code, we see the log appear as changed postalCode from 1234AB to 5678CD.

I added these examples to CodePen so you can try them out yourself.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter

Did you find this article valuable?

Support Chris Bongers by becoming a sponsor. Any amount is appreciated!

See recent sponsors |Β Learn more about Hashnode Sponsors
Β 
Share this