Why Proxy Cache Is Important in Valtio

Proxy Cache Is Based on WeakMap

Hi,

As we learned in an earlier post, creating a Proxy is as easy as this:

const p = new Proxy(target, handlers);

So, if we were to create a function to create a Proxy, it would look something like this:

function proxy(target) {
  const handlers = { ... };
  return new Proxy(target, handlers);
}

However, there is a slight problem with this approach depending on the use case. See the following behavior:

const obj = {};
const p1 = proxy(obj);
const p2 = proxy(obj);

console.log(p1 === p2); // ---> false

Since p1 and p2 are different Proxy instances, the comparison returns false.

Using WeakMap to Cache Proxies

How can we fix this? This is where WeakMap comes in.

const proxyCache = new WeakMap();

function proxy(target) {
  if (proxyCache.has(target)) {
    return proxyCache.get(target);
  }
  const handlers = { ... };
  const p = new Proxy(target, handlers);
  proxyCache.set(target, p);
  return p;
}

As you can see, the created Proxy is stored in a WeakMap, so it can be reused if the same target object is passed in again. This makes the previous example behave like this:

const obj = {};
const p1 = proxy(obj);
const p2 = proxy(obj);

console.log(p1 === p2); // ---> true

How Valtio Uses Proxy Cache

This is exactly how Valtio's proxy works, although the actual implementation is more advanced. Valtio also supports nested proxies, where assigning a property automatically turns the assigned value into a proxy.

The behavior looks like this:

import { proxy } from 'valtio/vanilla';

const p = proxy({});
const obj = {};
p.a = obj;
p.b = obj;

console.log(p.a === p.b); // ---> true

// By the way
console.log(p.a === obj); // ---> false because p.a is a Proxy object

If you are curious about how this works, check out Valtio's source code to see how WeakMap is used in practice:

Happy coding.

Reply

or to participate.