Utilities

Valtio provides a set of utility functions to handle more advanced use cases. These are available under the valtio/utils entry point.

import { devtools, subscribeKey, watch } from 'valtio/utils';

For vanilla JavaScript projects, import from valtio/vanilla/utils.


devtools

Integrates your Valtio state with the Redux DevTools Extension for powerful debugging, including state inspection and time-travel.

Usage:

import { proxy } from 'valtio';
import { devtools } from 'valtio/utils';

const state = proxy({ count: 0, text: 'hello' });

// Connect the state to the devtools
const unsubscribe = devtools(state, { name: 'My App State', enabled: true });

subscribeKey

Subscribes to changes of a specific primitive property on a proxy object. The callback is only fired when that particular property's value changes.

Usage:

import { proxy } from 'valtio';
import { subscribeKey } from 'valtio/utils';

const state = proxy({ count: 0, text: 'hello' });

// This callback only runs when `state.count` changes.
subscribeKey(state, 'count', (newCount) => {
  console.log('Count changed to:', newCount);
});

state.count++; // Fires the callback
state.text = 'world'; // Does not fire the callback

watch

Creates a reactive effect that tracks multiple proxy objects and re-runs a callback whenever any of them change. The callback receives a get function to register dependencies.

Usage:

import { proxy } from 'valtio';
import { watch } from 'valtio/utils';

const userState = proxy({ user: { name: 'Juuso' } });
const sessionState = proxy({ expired: false });

const stop = watch((get) => {
  // `get` tracks dependencies automatically
  const name = get(userState).user.name;
  const isExpired = get(sessionState).expired;
  console.log(`${name}'s session is ${isExpired ? 'expired' : 'valid'}`);
});

// The callback runs immediately, then again on any change to tracked proxies.
sessionState.expired = true;

// Stop watching for changes
stop();

proxyMap and isProxyMap

Creates a reactive Map that is compatible with Valtio. Native Map objects cannot be tracked, so proxyMap provides a proxy-based alternative that mimics the Map API.

Usage:

import { proxyMap } from 'valtio/utils';

const state = proxy({
  users: proxyMap([
    [1, { name: 'Alice' }],
    [2, { name: 'Bob' }],
  ]),
});

// Mutate it like a normal Map
state.users.set(3, { name: 'Charlie' });
state.users.delete(1);

// Check if an object is a proxyMap
import { isProxyMap } from 'valtio/utils';
isProxyMap(state.users); // true

proxySet and isProxySet

Creates a reactive Set that is compatible with Valtio. Similar to proxyMap, this utility provides a trackable alternative to the native Set.

Usage:

import { proxySet } from 'valtio/utils';

const state = proxy({
  tags: proxySet(['react', 'typescript']),
});

// Mutate it like a normal Set
state.tags.add('valtio');
state.tags.delete('react');

// Check if an object is a proxySet
import { isProxySet } from 'valtio/utils';
isProxySet(state.tags); // true

useProxy

A convenience hook for React that returns a special proxy. You can use this proxy for both reading in the render phase and for mutations in callbacks, simplifying the state/snapshot distinction. Note that mutations are only allowed on the root level of the returned proxy.

import { useProxy } from 'valtio/utils';

const state = proxy({ count: 1 });

const Component = () => {
  const $state = useProxy(state);
  return (
    <div>
      {$state.count} {/* Read from the proxy in render */}
      <button onClick={() => ++$state.count}>+1</button> {/* Mutate it in a callback */}
    </div>
  );
};

derive

Creates a new derived proxy state from other proxies. The derived values are recomputed whenever the source proxies change. This utility is available in a separate package: derive-valtio.

Usage:

import { proxy } from 'valtio';
import { derive } from 'derive-valtio';

const state = proxy({ count: 1 });

const derivedState = derive({
  doubled: (get) => get(state).count * 2,
});

// `derivedState.doubled` will be 2
// If `state.count` changes to 5, `derivedState.doubled` will become 10.

proxyWithHistory

Creates a proxy with undo/redo capabilities by tracking a history of snapshots. This utility is available in a separate package: valtio-history.

Usage:

import { proxyWithHistory } from 'valtio-history';

const state = proxyWithHistory({ count: 0 });

state.value.count += 1; // count is 1
state.undo(); // count is 0
state.redo(); // count is 1

unstable_deepProxy

A utility to recursively traverse an object and convert all proxiable objects into their Valtio equivalents (proxy, proxyMap, proxySet), respecting objects marked with ref().

Usage:

import { unstable_deepProxy as deepProxy } from 'valtio/utils';

const obj = {
  mySet: new Set([1]),
  myMap: new Map([['a', 1]]),
  nested: { value: 'foo' }
};

const proxiedObj = deepProxy(obj);
// proxiedObj.mySet is now a proxySet
// proxiedObj.myMap is now a proxyMap
// proxiedObj.nested is now a proxy