# valtio **Repository Path**: mirrors_fkhadra/valtio ## Basic Information - **Project Name**: valtio - **Description**: 💊 Valtio makes proxy-state simple for React and Vanilla - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-01-11 - **Last Updated**: 2026-10-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README valtio

npm i valtio makes proxy-state simple [![Build Status](https://img.shields.io/github/workflow/status/pmndrs/valtio/Lint?style=flat&colorA=000000&colorB=000000)](https://github.com/pmndrs/valtio/actions?query=workflow%3ALint) [![Build Size](https://img.shields.io/bundlephobia/minzip/valtio?label=bundle%20size&style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/result?p=valtio) [![Version](https://img.shields.io/npm/v/valtio?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/valtio) [![Downloads](https://img.shields.io/npm/dt/valtio.svg?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/valtio) [![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https://discord.gg/poimandres) #### Wrap your state object Valtio turns the object you pass it into a self-aware proxy. ```jsx import { proxy, useSnapshot } from 'valtio' const state = proxy({ count: 0, text: 'hello' }) ``` #### Mutate from anywhere You can make changes to it in the same way you would to a normal js-object. ```jsx setInterval(() => { ++state.count }, 1000) ``` #### React via useSnapshot Create a local snapshot that catches changes. Rule of thumb: read from snapshots, mutate the source. The component will only re-render when the parts of the state you access have changed, it is render-optimized. ```jsx // This will re-render on `state.count` change but not on `state.text` change function Counter() { const snap = useSnapshot(state) return (
{snap.count}
) } ```
Note: useSnapshot returns a new proxy for render optimization. Internally, `useSnapshot` calls `snapshot` in valtio/vanilla, and wraps the snapshot object with another proxy to detect property access. This feature is based on [proxy-compare](https://github.com/dai-shi/proxy-compare). Two kinds of proxies are used for different purposes: - `proxy()` from `valtio/vanilla` is for mutation tracking or write tracking. - `createProxy()` from `proxy-compare` is for usage tracking or read tracking.
Use of `this` is for expert users. Valtio tries best to handle `this` behavior but it's hard to understand without familiarity. ```js const state = proxy({ count: 0, inc() { ++this.count } }) state.inc() // `this` points to `state` and it works fine const snap = useSnapshot(state) snap.inc() // `this` points to `snap` and it doesn't work because snapshot is frozen ``` To avoid this pitfall, the recommended pattern is not to use `this` and prefer arrow function. ```js const state = proxy({ count: 0, inc: () => { ++state.count } }) ```
If you are new to this, it's highly recommended to use [eslint-plugin-valtio](https://github.com/pmndrs/eslint-plugin-valtio). #### Subscribe from anywhere You can access state outside of your components and subscribe to changes. ```jsx import { subscribe } from 'valtio' // Suscribe to all state changes const unsubscribe = subscribe(state, () => console.log('state has changed to', state)) // Unsubscribe by calling the result unsubscribe() ``` You can also subscribe to a portion of state. ```jsx const state = proxy({ obj: { foo: 'bar' }, arr: ['hello'] }) subscribe(state.obj, () => console.log('state.obj has changed to', state.obj)) state.obj.foo = 'baz' subscribe(state.arr, () => console.log('state.arr has changed to', state.arr)) state.arr.push('world') ``` To subscribe to a primitive value of state, consider `subscribeKey` in utils. ```jsx import { subscribeKey } from 'valtio/utils' const state = proxy({ count: 0, text: 'hello' }) subscribeKey(state, 'count', (v) => console.log('state.count has changed to', v)) ``` There is another util `watch` which might be convenient in some cases. ```jsx import { watch } from 'valtio/utils' const state = proxy({ count: 0 }) const stop = watch((get) => { console.log('state has changed to', get(state)) // auto-subscribe on use }) ``` #### Suspend your components Valtio supports React-suspense and will throw promises that you access within a components render function. This eliminates all the async back-and-forth, you can access your data directly while the parent is responsible for fallback state and error handling. ```jsx const state = proxy({ post: fetch(url).then((res) => res.json()) }) function Post() { const snap = useSnapshot(state) return
{snap.post.title}
} function App() { return ( waiting...}> ) } ``` #### Holding objects in state without tracking them This may be useful if you have large, nested objects with accessors that you don't want to proxy. `ref` allows you to keep these objects inside the state model. See [#61](https://github.com/pmndrs/valtio/issues/61) and [#178](https://github.com/pmndrs/valtio/issues/178) for more information. ```js import { proxy, ref } from 'valtio' const state = proxy({ count: 0, dom: ref(document.body), }) ``` #### Update transiently (for often occuring state-changes) You can read state in a component without causing re-render. ```jsx function Foo() { const { count, text } = state // ... ``` Or, you can have more control with subscribing in useEffect. ```jsx function Foo() { const total = useRef(0) useEffect(() => subscribe(state.arr, () => { total.current = state.arr.reduce((p, c) => p + c) }), [state.obj]) // ... ``` #### Update synchronously By default, state mutations are batched before triggering re-render. Sometimes, we want to disable the batching. The known use case of this is `` [#270](https://github.com/pmndrs/valtio/issues/270). ```jsx function TextBox() { const snap = useSnapshot(state, { sync: true }) return (state.text = e.target.value)} /> } ``` #### Dev tools You can use [Redux DevTools Extension](https://github.com/zalmoxisus/redux-devtools-extension) for plain objects and arrays. ```jsx import { devtools } from 'valtio/utils' const state = proxy({ count: 0, text: 'hello' }) const unsub = devtools(state, 'state name') ```
Manipulating state with Redux DevTools The screenshot below shows how to use Redux DevTools to manipulate state. First select the object from the instances drop down. Then type in a JSON object to dispatch. Then click "Dispatch". Notice how it changes the state. image
#### Use it vanilla Valtio is not tied to React, you can use it in vanilla-js. ```jsx import { proxy, subscribe, snapshot } from 'valtio/vanilla' const state = proxy({ count: 0, text: 'hello' }) subscribe(state, () => { console.log('state is mutated') const obj = snapshot(state) // A snapshot is an immutable object }) ``` #### `useProxy` macro We have a convenient macro with [babel-plugin-macros](https://www.npmjs.com/package/babel-plugin-macros). ```js import { useProxy } from 'valtio/macro' const Component = () => { useProxy(state) return (
{state.count}
) } // the code above becomes the code below. import { useSnapshot } from 'valtio' const Component = () => { const snap = useSnapshot(state) return (
{snap.count}
) } ``` #### `derive` util You can subscribe to some proxies and create a derived proxy. ```js import { derive } from 'valtio/utils' // create a base proxy const state = proxy({ count: 1, }) // create a derived proxy const derived = derive({ doubled: (get) => get(state).count * 2, }) // alternatively, attach derived properties to an existing proxy derive({ tripled: (get) => get(state).count * 3, }, { proxy: state, }) ``` #### `proxyWithComputed` util You can have computed values with dependency tracking with property access. Dependency tracking in `proxyWithComputed` conflicts with the work in `useSnapshot`. React users should prefer using `derive`. `proxyWithComputed` works well for some edge cases and for vanilla-js users. ```js import { proxyWithComputed } from 'valtio/utils' const state = proxyWithComputed({ count: 1, }, { doubled: snap => snap.count * 2 }) // Computed values accept custom setters too: const state2 = proxyWithComputed({ firstName: 'Alec', lastName: 'Baldwin' }, { fullName: { get: (snap) => snap.firstName + ' ' + snap.lastName, set: (state, newValue) => { [state.firstName, state.lastName] = newValue.split(' ') }, } }) // if you want a computed value to derive from another computed, you must declare the dependency first: const state = proxyWithComputed({ count: 1, }, { doubled: snap => snap.count * 2, quadrupled: snap => snap.doubled * 2 }) ``` The last use case fails to infer types in TypeScript [#192](https://github.com/pmndrs/valtio/issues/192). #### `proxyWithHistory` util This is a utility function to create a proxy with snapshot history. ```js import { proxyWithHistory } from 'valtio/utils' const state = proxyWithHistory({ count: 0 }) console.log(state.value) // ---> { count: 0 } state.value.count += 1 console.log(state.value) // ---> { count: 1 } state.undo() console.log(state.value) // ---> { count: 0 } state.redo() console.log(state.value) // ---> { count: 1 } ``` #### Plugins - [eslint-plugin-valtio](https://github.com/pmndrs/eslint-plugin-valtio) #### Recipes Valtio is unopinionated about best practices. The community is working on recipes on wiki pages. - [How to organize actions](https://github.com/pmndrs/valtio/wiki/How-to-organize-actions) - [How to persist states](https://github.com/pmndrs/valtio/wiki/How-to-persist-states) - [How to use with context](https://github.com/pmndrs/valtio/wiki/How-to-use-with-context) - [How to split and compose states](https://github.com/pmndrs/valtio/wiki/How-to-split-and-compose-states)