Learn How Jotai Uses a Symbol for Internal API

Exploring How Jotai v2.12.0 Exposes Its Internal API

Hi,

Jotai v2.12.0 has been released. It has been planned for a while, but it took time to finalize the API. This minor version does not change the public API, and it does not even change the logic. However, it is a significant refactor that now allows some internals to be exposed.

Exposing pure functions is simple since we can just export them. We use the INTERNAL_ prefix to indicate that they are not for public use. The challenge was how to expose the internal store state and store functions that are tied to store state. We refer to them collectively as building blocks and expose them using a symbol. Essentially, it looks like this:

const BUILDING_BLOCKS = Symbol();

const buildStore = () => {
  const atomStateMap = new WeakMap();
  const mountedMap = new WeakMap();
  // ...
  const readAtomState = (atom) => // ...
  // ...

  const store = {
    get: // ...
    set: // ...
    sub: // ...
    [BUILDING_BLOCKS]: [
      atomStateMap,
      mountedMap,
      // ...
      readAtomState,
      // ...
    ],
  };

  return store;
};

To retrieve the building blocks from the store, we need the symbol. Instead of exporting the symbol variable, we create a getter function. This keeps the symbol as an implementation detail.

const getBuildingBlocks = (store) => store[BUILDING_BLOCKS];

Finally, we export these functions with the INTERNAL_ prefix.

export const INTERNAL_buildStore = buildStore;
export const INTERNAL_getBuildingBlocks = getBuildingBlocks;

This approach still relies on the symbol as a module state, which is affected by the dual module issue, but it remains clean and self-explanatory.

There are additional details, and if you are interested, feel free to check out the source code in the repository.

Happy coding.

Reply

or to participate.