Building Reactive Objects
Introduction: From Logging to Reactivity
In our first lesson, we learned how to use the Proxy object and the Reflect API to create a logging tool. We saw how to watch an object and print a message every time someone accessed or changed a property. While logging is a great way to debug your code, we can take this concept much further.
The idea of "reactivity" is a core part of modern web development. You might have used frameworks like Vue or libraries that automatically update the screen whenever your data changes. This happens because the system is "reacting" to changes in your data. In this lesson, we are going to build our own reactive state system. Instead of just printing to the console, our proxy will trigger a specific callback function whenever a property is updated or deleted. This allows us to build applications that stay in sync with their data automatically.
The Basic Reactive Proxy Pattern
To build a reactive system, we need a function that takes an object and an onChange callback. Every time a change happens, the proxy should execute that callback. We focus on two main traps: set and deleteProperty. The set trap handles when a property is added or changed, and the deleteProperty trap handles when a property is removed.
In the code below, we use Reflect.set to update the object and then check whether the operation was successful. If it was successful, we call onChange with the property name, the old value, and the new value. This tells the rest of our program exactly what changed so that it can react accordingly.
This simple version works well for flat objects. If you change a top-level property, the callback runs. However, if your object has other objects inside it, this basic version will not notice changes deep inside those nested objects. Notice the deleteProperty trap first checks Reflect.has(obj, prop). Deleting a property that does not exist still succeeds (it returns true), so without this guard we would emit a misleading change event for a property that was never there.
