Using the Proxy API for State Management

Rate this content
Bookmark
The video covers using the JavaScript Proxy API for state management, highlighting the benefits of using proxies to observe and handle changes in objects. It explains basic proxy methods like get and set traps, and the role of the Reflect object in forwarding operations to the original object. The talk includes a demo on creating a proxy to observe changes to an object, emphasizing how proxies can be used like normal objects. It mentions the importance of avoiding proxies on primitive objects and introduces Taits, a state management library that uses the proxy API. The video also touches on the performance implications of proxies and compares them to other methods like object.observe and object.defineProperty.

From Author:

With so many libraries to choose from for state management, why not add one more? The ECMAScript Proxy API enables you to intercept and redefine how an object operates. Let's explore how you might use the Proxy API for state management!

This talk has been presented at JSNation Live 2021, check out the latest edition of this JavaScript Conference.

FAQ

Will Johnston is a developer advocate on WP Engine's DevRel team with extensive experience in web and back-end development, particularly in the Node.js, JavaScript, and TypeScript ecosystems.

The receiver provides the proper context to the Reflect object within a proxy handler, ensuring that operations are forwarded correctly to the original object.

Taits is a small state management library that uses the proxy API to observe changes to state objects. It allows you to create proxies and subscribe to changes on specific paths within those proxies.

While proxies may introduce some performance overhead compared to normal JavaScript operations, they are generally fast enough for most use cases. However, for highly performance-sensitive applications, alternatives may be considered.

A JavaScript Proxy is an object that allows you to intercept and customize operations performed on another object, such as property lookups, assignments, and function invocations. It provides a way to define custom behavior for fundamental operations on objects.

Proxies are similar to object.observe and object.defineProperty in that they allow you to observe and define custom behavior on objects. However, proxies are more feature-rich and provide a broader range of capabilities for intercepting operations on objects.

The Reflect object is used to forward operations to the original object in a proxy. This ensures that the original operations are performed correctly and helps avoid issues related to inheritance and other complexities.

'Get' and 'set' traps are methods in a proxy handler that intercept property access and assignment operations. The 'get' trap intercepts property access, while the 'set' trap intercepts property assignments.

To avoid creating a proxy on a primitive object, you can check the type of the value before creating the proxy. For example: ```javascript if (typeof value !== 'object' || value === null) { return value; } ```

A simple proxy handler in JavaScript can be created with 'get' and 'set' traps. For example: ```javascript const handler = { get: (target, property) => { console.log(`Getting ${property}`); return target[property]; }, set: (target, property, value) => { console.log(`Setting ${property} to ${value}`); target[property] = value; return true; } }; const proxy = new Proxy({}, handler); proxy.name = 'Will'; console.log(proxy.name); ```

Will Johnston
Will Johnston
27 min
09 Jun, 2021

Comments

Sign in or register to post your comment.

Video Transcription

1. Introduction to Proxies

Short description:

Hi, I'm Will Johnston, a developer advocate on WP Engine's DevRel team. Today, I'll discuss using proxies or the JavaScript Proxy API for state management.

♪♪ Hi, I'm Will Johnston. I'm a developer advocate on WP Engine's DevRel team, and I'm here today to talk to you about how you might use proxies or the JavaScript Proxy API for state management. Proxies, if you're unfamiliar, are a way that you can observe some of the underlying operations on objects within JavaScript. So if you're familiar with object.observe, which doesn't exist anymore, but that was kind of the precursor to proxies. And if you're also familiar with property descriptors or object.defineProperty, that's a similar thing to proxies. Proxies just enable a little bit more full features.

2. Introduction to Proxies (continued)

Short description:

I have been writing code since I was about 10 years old. I got interested in proxies to understand what's happening underneath. Proxy methods like get and set traps are simple and easy to grasp. Reflect is used to forward operations onto the original object and avoid inheritance issues. Let's create a basic demo using proxy to observe changes to an object. We intercept get and set operations and log them. We can use the proxy like a normal object.

A little bit about myself. I have been writing code since I was about 10 years old. In high school, I got a job doing some web programming with Python, and I really fell in love with software at that time and software development, and I've been a constant learner since then. I spent most of my career working on the web and back-end, and over the past few years, probably six to eight years, I've been working mostly with Node in the JavaScript and TypeScript ecosystem.

So, I really got interested in proxies because I've done a fair amount of .NET and C Sharp code, and in C Sharp, you have a concept of getters and setters on an object, and it allows you to stealthily poke into different operations on that object, and proxies function in a similar manner but for JavaScript. So, I got really interested into proxies to try to figure out how I can make that work because I really love when you can just use objects as you normally would, but underneath, you can understand exactly what's happening.

So, there are plenty of proxy methods, and proxy methods are used to set up traps, so you can observe some of the inherent ability for JavaScript to be performing different functions, so that's what a trap is. We're going to use the get and set traps today because those are simple and easy to grasp, and I'm not trying to go too far in depth with the short time that we have.

Something to know, when you're using proxy, you really also need to be using reflect, so the reflect object is used to forward all the operations onto the original object, so if you think of proxy is in front and you're listening to the set method, when somebody tries to set, you want to use the reflect object to eventually forward that operation on and actually set the value on that object. The reason you do this is related to avoiding this in inheritance issues, so if you create a proxy and then you try to inherit from it and you don't use reflect, you're going to get some wonky functionality where you're actually changing the original object, not the inherited object.

So let's just start with a basic demo, let's get a state object up using proxy to observe changes to that object, so we will, I like to create a proxy handler, it's the easiest way, I know that I'm going to eventually have to create a new object, a new proxy, and we will create an object and our handler is gonna be our proxy handler, so we know that our proxy handler is going to be a type proxy handler and that's where we have our get and our set methods, so let's create those now, target property and set target property value. So the get method just returns the target, the property at a certain target and the set method sets the value of a property on a target, so in here, we'll say getting property value value to be in here, we will say setting property oops and we will use the reflect API and this is how we can, it just mimics the proxy API directly. And allows us to not have to worry about what actually happens underneath, we just want to poke in where we care about it and observe the change. There's one additional piece we care about here and that is called the receiver and we want to add that in there. The receiver is going to provide the reflect object with that proper context. So here we have our get, our set, we are just intercepting these operations and logging, pretty simple.

For this, let's create on our state, a person, we'll say first name, Will. And let's go ahead and just add a last name too. Johnston, all right. And then, in order to actually see what's going on here, we will have to console.log, state.person.firstname. So what we expect here is it's going to log, you know, getting person on here. You might expect it to log getting firstname as well. We'll see whether it does in a second. Spoiler alert, it does not. And I'm just going to say here, and I'll call William. So we'll try to set the first name and that's good. All right. So note, when we create this proxy, we can just use state like a normal object. We don't have to care. So if you had, typically you'll use a library that might be using proxy underneath.

QnA