[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-70726":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":19,"stars90d":16,"forks30d":16,"starsTrendScore":20,"compositeScore":21,"rankGlobal":10,"rankLanguage":10,"license":22,"archived":23,"fork":23,"defaultBranch":24,"hasWiki":25,"hasPages":23,"topics":26,"createdAt":10,"pushedAt":10,"updatedAt":31,"readmeContent":32,"aiSummary":33,"trendingCount":16,"starSnapshotCount":16,"syncStatus":15,"lastSyncTime":34,"discoverSource":35},70726,"valtio","pmndrs\u002Fvaltio","pmndrs","🧙 Valtio makes proxy-state simple  for React and Vanilla","https:\u002F\u002Fvaltio.dev",null,"TypeScript",10194,283,35,2,0,1,7,11,3,42.36,"MIT License",false,"main",true,[27,28,29,30],"mutable","proxy","react","state","2026-06-12 02:02:42","\u003Cimg src=\"logo.svg\" alt=\"valtio\">\n\u003Cbr \u002F>\n\u003Cbr \u002F>\n\n\u003Ccode>npm install valtio\u003C\u002Fcode> makes proxy-state simple\n\n[![Build Status](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fpmndrs\u002Fvaltio\u002Ftest.yml?branch=main&style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Factions\u002Fworkflows\u002Ftest.yml?query=branch%3Amain)\n[![Build Size](https:\u002F\u002Fimg.shields.io\u002Fbundlephobia\u002Fminzip\u002Fvaltio?label=bundle%20size&style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fbundlephobia.com\u002Fresult?p=valtio)\n[![Version](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fvaltio?style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvaltio)\n[![Downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Fvaltio.svg?style=flat&colorA=000000&colorB=000000)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fvaltio)\n[![Discord Shield](https:\u002F\u002Fimg.shields.io\u002Fdiscord\u002F740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https:\u002F\u002Fdiscord.gg\u002Fpoimandres)\n\n#### Wrap your state object\n\nValtio turns the object you pass it into a self-aware proxy.\n\n```jsx\nimport { proxy, useSnapshot } from 'valtio'\n\nconst state = proxy({ count: 0, text: 'hello' })\n```\n\n#### Mutate from anywhere\n\nYou can make changes to it in the same way you would to a normal js-object.\n\n```jsx\nsetInterval(() => {\n  ++state.count\n}, 1000)\n```\n\n#### React via useSnapshot\n\nCreate a local snapshot that catches changes. Rule of thumb: read from snapshots in render function, otherwise use the source. The component will only re-render when the parts of the state you access have changed, it is render-optimized.\n\n```jsx\n\u002F\u002F This will re-render on `state.count` change but not on `state.text` change\nfunction Counter() {\n  const snap = useSnapshot(state)\n  return (\n    \u003Cdiv>\n      {snap.count}\n      \u003Cbutton onClick={() => ++state.count}>+1\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n\u003Cdetails>\n\u003Csummary>Note for TypeScript users: Return type of useSnapshot can be too strict.\u003C\u002Fsummary>\n\nThe `snap` variable returned by `useSnapshot` is a (deeply) read-only object.\nIts type has `readonly` attribute, which may be too strict for some use cases.\n\nTo mitigate typing difficulties, you might want to loosen the type definition:\n\n```ts\ndeclare module 'valtio' {\n  function useSnapshot\u003CT extends object>(p: T): T\n}\n```\n\nSee [#327](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fissues\u002F327) for more information.\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Note: useSnapshot returns a new proxy for render optimization.\u003C\u002Fsummary>\n\nInternally, `useSnapshot` calls `snapshot` in valtio\u002Fvanilla,\nand wraps the snapshot object with another proxy to detect property access.\nThis feature is based on [proxy-compare](https:\u002F\u002Fgithub.com\u002Fdai-shi\u002Fproxy-compare).\n\nTwo kinds of proxies are used for different purposes:\n\n- `proxy()` from `valtio\u002Fvanilla` is for mutation tracking or write tracking.\n- `createProxy()` from `proxy-compare` is for usage tracking or read tracking.\n\u003C\u002Fdetails>\n\n\u003Cdetails>\n\u003Csummary>Use of \u003Ccode>this\u003C\u002Fcode> is for expert users.\u003C\u002Fsummary>\n\nValtio tries best to handle `this` behavior\nbut it's hard to understand without familiarity.\n\n```js\nconst state = proxy({\n  count: 0,\n  inc() {\n    ++this.count\n  },\n})\nstate.inc() \u002F\u002F `this` points to `state` and it works fine\nconst snap = useSnapshot(state)\nsnap.inc() \u002F\u002F `this` points to `snap` and it doesn't work because snapshot is frozen\n```\n\nTo avoid this pitfall, the recommended pattern is not to use `this` and prefer arrow function.\n\n```js\nconst state = proxy({\n  count: 0,\n  inc: () => {\n    ++state.count\n  },\n})\n```\n\n\u003C\u002Fdetails>\n\nIf you are new to this, it's highly recommended to use\n[eslint-plugin-valtio](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Feslint-plugin-valtio).\n\n#### Subscribe from anywhere\n\nYou can access state outside of your components and subscribe to changes.\n\n```jsx\nimport { subscribe } from 'valtio'\n\n\u002F\u002F Subscribe to all state changes\nconst unsubscribe = subscribe(state, () =>\n  console.log('state has changed to', state),\n)\n\u002F\u002F Unsubscribe by calling the result\nunsubscribe()\n```\n\nYou can also subscribe to a portion of state.\n\n```jsx\nconst state = proxy({ obj: { foo: 'bar' }, arr: ['hello'] })\n\nsubscribe(state.obj, () => console.log('state.obj has changed to', state.obj))\nstate.obj.foo = 'baz'\n\nsubscribe(state.arr, () => console.log('state.arr has changed to', state.arr))\nstate.arr.push('world')\n```\n\nTo subscribe to a primitive value of state, consider `subscribeKey` in utils.\n\n```jsx\nimport { subscribeKey } from 'valtio\u002Futils'\n\nconst state = proxy({ count: 0, text: 'hello' })\nsubscribeKey(state, 'count', (v) =>\n  console.log('state.count has changed to', v),\n)\n```\n\nThere is another util `watch` which might be convenient in some cases.\n\n```jsx\nimport { watch } from 'valtio\u002Futils'\n\nconst state = proxy({ count: 0 })\nconst stop = watch((get) => {\n  console.log('state has changed to', get(state)) \u002F\u002F auto-subscribe on use\n})\n```\n\n#### Suspend your components\n\nValtio is compatible with React 19 `use` hook. 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.\n\n```jsx\nimport { use } from 'react' \u002F\u002F React 19\n\u002F\u002F import { use } from 'react18-use' \u002F\u002F React 18\n\nconst state = proxy({ post: fetch(url).then((res) => res.json()) })\n\nfunction Post() {\n  const snap = useSnapshot(state)\n  return \u003Cdiv>{use(snap.post).title}\u003C\u002Fdiv>\n}\n\nfunction App() {\n  return (\n    \u003CSuspense fallback={\u003Cspan>waiting...\u003C\u002Fspan>}>\n      \u003CPost \u002F>\n    \u003C\u002FSuspense>\n  )\n}\n```\n\nIt still suffers from \"de-opt\", which prevents `useTransition` to work well. To mitigate it, there is a third-party library [use-valtio](https:\u002F\u002Fgithub.com\u002Fvaltiojs\u002Fuse-valtio).\n\n#### Holding objects in state without tracking them\n\nThis 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.\n\nSee [#61](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fissues\u002F61) and [#178](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fissues\u002F178) for more information.\n\n```js\nimport { proxy, ref } from 'valtio'\n\nconst state = proxy({\n  count: 0,\n  dom: ref(document.body),\n})\n```\n\n#### Update transiently (for often occurring state-changes)\n\nYou can read state in a component without causing re-render.\n\n```jsx\nfunction Foo() {\n  const { count, text } = state\n  \u002F\u002F ...\n```\n\nOr, you can have more control with subscribing in useEffect.\n\n```jsx\nfunction Foo() {\n  const total = useRef(0)\n  useEffect(() => subscribe(state.arr, () => {\n    total.current = state.arr.reduce((p, c) => p + c)\n  }), [])\n  \u002F\u002F ...\n```\n\n#### Update synchronously\n\nBy default, state mutations are batched before triggering re-render.\nSometimes, we want to disable the batching.\nThe known use case of this is `\u003Cinput>` [#270](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fissues\u002F270).\n\n```jsx\nfunction TextBox() {\n  const snap = useSnapshot(state, { sync: true })\n  return (\n    \u003Cinput value={snap.text} onChange={(e) => (state.text = e.target.value)} \u002F>\n  )\n}\n```\n\n#### Dev tools\n\nYou can use [Redux DevTools Extension](https:\u002F\u002Fgithub.com\u002Freduxjs\u002Fredux-devtools) for plain objects and arrays.\n\n```jsx\nimport { devtools } from 'valtio\u002Futils'\n\nconst state = proxy({ count: 0, text: 'hello' })\nconst unsub = devtools(state, { name: 'state name', enabled: true })\n```\n\n\u003Cdetails>\n  \u003Csummary>Manipulating state with Redux DevTools\u003C\u002Fsummary>\nThe 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.\n\n\u003Cbr\u002F>\n\u003Cimg width=\"564\" alt=\"image\" src=\"https:\u002F\u002Fuser-images.githubusercontent.com\u002F6372489\u002F141134955-26e9ffce-1e2a-4c8c-a9b3-d9da739610fe.png\">\n\u003C\u002Fdetails>\n\n#### Use it vanilla\n\nValtio is not tied to React, you can use it in vanilla-js.\n\n```jsx\nimport { proxy, subscribe, snapshot } from 'valtio\u002Fvanilla'\n\u002F\u002F import { ... } from 'valtio\u002Fvanilla\u002Futils'\n\nconst state = proxy({ count: 0, text: 'hello' })\n\nsubscribe(state, () => {\n  console.log('state is mutated')\n  const obj = snapshot(state) \u002F\u002F A snapshot is an immutable object\n})\n```\n\n#### `useProxy` util\n\nWhile the separation of proxy state and its snapshot is important,\nit's confusing for beginners.\nWe have a convenient util to improve developer experience. useProxy returns shallow proxy state and its snapshot, meaning you can only mutate on root level.\n\n```js\nimport { useProxy } from 'valtio\u002Futils'\n\nconst state = proxy({ count: 1 })\n\nconst Component = () => {\n  \u002F\u002F useProxy returns a special proxy that can be used both in render and callbacks\n  \u002F\u002F The special proxy has to be used directly in a function scope. You can't destructure it outside the scope.\n  const $state = useProxy(state)\n  return (\n    \u003Cdiv>\n      {$state.count}\n      \u003Cbutton onClick={() => ++$state.count}>+1\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  )\n}\n```\n\n#### Computed properties\n\nYou can define computed properties with object getters.\n\n```js\nconst state = proxy({\n  count: 1,\n  get doubled() {\n    return this.count * 2\n  },\n})\n```\n\nConsider it as an advanced usage, because the behavior of `this` is sometimes confusing.\n\nFor more information, check out [this guide](.\u002Fdocs\u002Fguides\u002Fcomputed-properties.mdx).\n\n#### `proxySet` util\n\nThis is to create a proxy which mimic the native Set behavior. The API is the same as Set API\n\n```js\nimport { proxySet } from 'valtio\u002Futils'\n\nconst state = proxySet([1, 2, 3])\n\u002F\u002Fcan be used inside a proxy as well\n\u002F\u002Fconst state = proxy({\n\u002F\u002F    count: 1,\n\u002F\u002F    set: proxySet()\n\u002F\u002F})\n\nstate.add(4)\nstate.delete(1)\nstate.forEach((v) => console.log(v)) \u002F\u002F 2,3,4\n```\n\n#### `proxyMap` util\n\nThis is to create a proxy which emulate the native Map behavior. The API is the same as Map API\n\n```js\nimport { proxyMap } from 'valtio\u002Futils'\n\nconst state = proxyMap([\n  ['key', 'value'],\n  ['key2', 'value2'],\n])\nstate.set('key', 'value')\nstate.delete('key')\nstate.get('key') \u002F\u002F ---> value\nstate.forEach((value, key) => console.log(key, value)) \u002F\u002F ---> \"key\", \"value\", \"key2\", \"value2\"\n```\n\n#### Compatibility\n\nValtio v2 works with React 18 and up.\nIt only depends on `react` and works with any\nrenderers such as `react-dom`, `react-native`, `react-three-fiber`, and so on.\n\nValtio works on Node.js, Next.js and other frameworks.\n\nValtio also works without React. See [vanilla](#use-it-vanilla).\n\n#### Plugins\n\n- [eslint-plugin-valtio](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Feslint-plugin-valtio)\n\n#### Recipes\n\nValtio is unopinionated about best practices.\nThe community is working on recipes.\n\n- [How to organize actions](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fblob\u002Fmain\u002Fdocs\u002Fhow-tos\u002Fhow-to-organize-actions.mdx)\n- [How to persist states](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fblob\u002Fmain\u002Fdocs\u002Fhow-tos\u002Fhow-to-persist-states.mdx)\n- [How to use with context](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fblob\u002Fmain\u002Fdocs\u002Fhow-tos\u002Fhow-to-use-with-context.mdx)\n- [How to split and compose states](https:\u002F\u002Fgithub.com\u002Fpmndrs\u002Fvaltio\u002Fblob\u002Fmain\u002Fdocs\u002Fhow-tos\u002Fhow-to-split-and-compose-states.mdx)\n","Valtio 是一个用于简化 React 和原生 JavaScript 应用程序中状态管理的库。它通过代理对象来追踪状态变化，允许开发者以操作普通 JavaScript 对象的方式修改状态，并且能够自动检测到这些变化。Valtio 的核心功能包括使用 `proxy` 方法创建可观察的状态对象以及利用 `useSnapshot` 钩子在 React 组件中高效地订阅状态更新，只在访问的数据发生变化时触发重新渲染，从而优化性能。适用于需要轻量级、易于上手的状态管理解决方案的场景，特别适合于小型到中等规模的应用或项目中的状态管理需求。","2026-06-11 03:33:50","high_star"]