Skip to content

Instantly share code, notes, and snippets.

@faceyspacey
Created June 29, 2024 01:38
Show Gist options
  • Save faceyspacey/52f85541733e98d793aaa958d4071390 to your computer and use it in GitHub Desktop.
Save faceyspacey/52f85541733e98d793aaa958d4071390 to your computer and use it in GitHub Desktop.
How Valtio Works

Valtio - How it Works!

So the way Valtio works is the proxy() function is passed an object, which it wraps in a proxy via proxyFunction(). This proxy has a trap for "set" and "deleteProperty" which notifies interested listeners whenever a value is set on any of the keys of the object.

If the proxy finds that you assign another object, it recursively calls proxyFunction again with this object, wrapping it in another similar proxy, in case it too has values assigned to its keys. And so on. On first call to proxy() the entire object is traversed, applying proxy traps to nested objects.

Thereafter, whenever a value is assigned to a key, subscribed listeners to those keys are called recursively up to the top of the object, finalizing with a call to the callback supplied to useSyncExternalStore in useSnapshot hooks, resulting in a re-render of its containing component, if that component accessed changed keys.

The way the subscription mechanism works is that when useSnapshot subscribes to the proxy, it recursively applies listeners to all nested child objects. (It does so lazily, only as nested objects are accessed). Then when the "set" trap is triggered on any child, each listener in turn calls a listener on the parent until it reaches the listener/callback in components that used useSnapshot.

In essence, each call to subscribe adds a listener to the top level parent object, which attaches a new kind of listener to children, whose job when notified is to call parent listeners, and so on back to the top, where useSnapshot will re-render the component if it detects a change.

When useSnapshot is notified, it will take the resulting state and compare it to what it previously had, but only by looking at the object keys it in fact is using, minimizing the amount of work that needs to be done. This is done with a WeakMap that stores references to the keys on each object accessed.

isChanged then recursively examines used keys to see if the previous state's value matches the current state's value. If it has changed, it returns true, and useSyncExternalStore knows to re-render. If one of those keys that changed is an object, isChanged will call isChanged recursively on the prev/next children until it finds a primitive value that did in fact change.

WeakMaps are used to attach used keys to accessed objects in order to automatically allow all the references and metadata to be garbage collected.

Lastly, if new objects are attached, listeners will be recursively added, which when notified will call back up to the top level useSnapshot re-rendering mechanism.

Respond Framework Modifications to Valtio

Respond modules have modified Valtio by applying getters to the initial proxy, which return calls to selectors on the appropriate keys of objects corresponding to modules.

Respond modules have modified proxyCompare which is used by useSnapshot to detect if only used keys have changed, by ignoring selectors on module objects, and picking back up with access to reducer state within those selectors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment