How to Batch Updates in Valtio

Do You Know the queueMicrotask Function?

Hi,

When designing the Valtio API, I wanted to make it as straightforward as possible. In other words, I aimed for a "Just JS" approach, which means using as few APIs as possible.

Subscribing to State Changes

Valtio provides a mechanism to subscribe to state changes. Let’s look at a simple example:

import { proxy, subscribe } from 'valtio/vanilla';

const state = proxy({ count: 0 });
subscribe(state, () => {
  console.log('count:', state.count);
});

state.count++; // ---> shows "count: 1"

Simple enough. But what happens if we do this?

state.count++;
state.count++;

Should we see the console log twice or just once?

The Design Decision

This is a design choice. I wanted the console log to appear only once, but without introducing any new APIs.

The solution was to delay invoking the callback using a microtask. As far as I remember, I learned about this technique from Preact.

Using queueMicrotask for Batching

The function that schedules a callback to run in a microtask is called queueMicrotask.

Using this function, we can delay calling the callback function passed to subscribe. As a result, incrementing count twice synchronously only triggers the console log once.

By the way, in Valtio’s implementation, we use Promise.resolve().then(...) instead of queueMicrotask(...). This was originally done to support environments that did not have queueMicrotask, though such environments may no longer be relevant today.

Happy coding.

Reply

or to participate.