DEV Community

M. Andrew Darts
M. Andrew Darts

Posted on

Vanilla change detection with Proxies in Javascript

In a smaller project with just a little interactivity you may want to keep up with a bit of state. If you have worked with Redux, MobX, NGRX or any other state management library your first inclination may be to use what you are familiar with. Let's be cheap and look to the platform and see what tools we can use to get this done without a library.

Proxies

Proxies are somewhat a new concept in Javascript. Proxies simply provide a way to enhance an object, some examples are listeners, dynamic properties and validation. Quick example.


const person = { firstName: "Luke", lastName: "Skywalker" };


const personHandler = {
  set: function(obj, prop, value) {
   console.log(`${prop} changed from ${obj[prop]} to ${value}`);
   obj[prop] = value;
   return true;
  }
};


const personProxy = new Proxy(person, personHandler);

personProxy.firstName = "Not Luke";
// console.logs "firstName changed from Luke to Not Luke";

Enter fullscreen mode Exit fullscreen mode

In just 10 lines of code we have implemented a simple proxy that logs the changes of an object.

One small step

Let's take this a step further. Say we want to keep up with a list of notes. These notes will need to be rendered on the page. We need a simple way to update the notes array and those changes be reflected to the page without thinking. If we think about it the data is the source of truth and the rendering is a side effect. That being said let's create a Proxy factory that will take in an object to observe and an array of functions to run when the object changes.

export const observer = (obj, ...listeners) => {
  return new Proxy(obj, {
    set: function(obj, prop, value) {
      listeners.forEach(fn => fn({...obj, [prop]: value}, obj));
      obj[prop] = value;
      return true;
    }
  })
}

Enter fullscreen mode Exit fullscreen mode

What is this ☝️?
This is a factory function that will create proxies and run some functions when it changes. How do I use this?

const notesObserver = observer(
 { notes: [{ text: "Do something." }] }, 
 renderNotes,
 logChanges
);

function renderNotes(notes) {
  // render notes here...
}

function logChanges(notes, oldNotes) {
  console.log(notes, oldNotes);
}
Enter fullscreen mode Exit fullscreen mode

Below is a working example. As the web platform grows things will only get more exciting! Think of all the cool things that could be done with Proxies. Would love to hear thoughts and ideas!

Here is an example of the notes app working with Proxies.

Top comments (0)