1. 18
    Use reactive variables to hold local client state in Apollo's cache
    3m 43s

Use reactive variables to hold local client state in Apollo's cache

Rares Matei
InstructorRares Matei

Share this video with your friends

Send Tweet
Published 9 months ago
Updated 6 months ago

We're going to complete our note selection example by adding reactive variables to the mix. These can be created via Apollo's "makeVar()" utility. Same as normal variables, they can be instantiated, read, and updated. The difference is that if we return them from "read" field policies, whenever they get updated, they'll signal to Apollo that that particular field has changed, and it should re-render the components.

Instructor: [0:00] Toggling our checkbox doesn't really do anything useful right now, and we don't have a way to change the note selection status. I'll go to my top-level index.js file, and I'll create a setNoteSelection function. It will accept a note ID and whether that note should now be selected or not.

[0:17] If the note should be selected, then we'll add that note ID to our selected note ID's array. Let's make it a let here, so it allows us to reassign it. If the note has been deselected, I'll filter out its ID from the selection list. Let me add some logging to see the selection status before our transformations, and then after.

[0:41] Back where my checkbox is, I can now invoke it and pass my current note ID and the new selection status to it. Back in my browser, if I click the second note to deselect it, I can see its ID gets removed correctly from the list, but it's still selected in the UI. Same for the first note. If I click it, the ID gets added to our selected notes list, but it remains deselected here.

[1:06] Whenever we change this list, Apollo has no idea something changed. It has no idea it needs to read from the cache again so that it can get the update, but Apollo has a concept of reactive variables, which we can import from the @apollo/client package.

[1:22] To initialize a reactive variable, you call makeVar with the initial value. To read it, you invoke it as a function. To update it, you invoke it with a new value. Let's read it again to see if it updated.

[1:36] If we test this in the browser, we can see that the value starts out at one, but after it's updated, it becomes five. It turns out that if we make our selected note IDs a reactive variable, and instead of assigning to it, I invoke it with a new value. To get its current value here, I need to invoke it. Here as well, I'll call it with the new value.

[2:00] Call it to get its existing value before applying filter on it. It turns out that if I now use my new reactive variable and my TypePolicies and I read from it here, whenever this variable is updated back up in my function, it will also signal to Apollo that it should read again.

[2:18] If we go back to the browser, we can see that note selection works fine now. If I open up the full note up here, the selection status is now kept in sync between the two. Awesome.

[2:30] We've just seen how to use reactive variables that you can initialize with a default value, update by invoking them with a new value, and read by calling them without any value. We then use them in our TypePolicy down here, to signal to Apollo that something has changed in the cache.

[2:48] This, in turn, causes it to re-read the isSelected field on each note, and re-render the React components accordingly. We've also seen how to query local state in our components. This gives us a central location where our components can decide what data they want, regardless of whether that data is coming from the server or it's just stored on the client.

[3:11] Querying them this way, and then passing them to the useQuery hook, gives Apollo a chance to automatically re-render any component listening to slices of the updated data. Most interestingly, this technique allows us to incrementally migrate to GraphQL.

[3:27] If the server is not ready yet, but we want to start getting our front end ready beforehand, we can begin with making all these fields client-only. As they start being implemented on the back end, we can start removing the client flag from here.