Valtio里怎么监听某个状态的变化?

公孙景苑 阅读 13

我用Valtio做状态管理,现在想在某个值变化时执行副作用,比如发请求或者打日志。试过直接在组件里写useEffect(() => { ... }, [proxy.value]),但发现依赖数组里的值根本不会触发更新,组件根本不重新渲染。

是不是得用它自带的subscribe?但我看文档有点懵,不知道该怎么正确订阅单个字段。下面是我现在的写法:

import { proxy, useSnapshot } from 'valtio'

const state = proxy({ count: 0, name: 'foo' })

function MyComponent() {
  const snap = useSnapshot(state)
  
  useEffect(() => {
    console.log('count changed:', snap.count)
  }, [snap.count]) // 这个好像不生效?

  return <div>{snap.count}</div>
}

到底该怎么监听 Valitio 里某个属性的变化啊?

我来解答 赞 1 收藏
二维码
手机扫码查看
1 条解答
❤俊贺
❤俊贺 Lv1
你的问题在于snap.count从Proxy对象里提取出来后就变成原始值了,useEffect的依赖数组根本检测不到变化。

Valtio监听变化要用subscribe,不是useEffect的依赖数组。正确写法:

import { proxy, useSnapshot, subscribe } from 'valtio'

const state = proxy({ count: 0, name: 'foo' })

function MyComponent() {
const snap = useSnapshot(state)

useEffect(() => {
const unsub = subscribe(state, () => {
// 这里写你的副作用逻辑
console.log('count变化了:', state.count)
// 发请求之类的操作放这里
}, { path: ['count'] }) // 关键:path选项只监听count字段

return unsub
}, [])

return
{snap.count}

}


{ path: ['count'] }这个参数很重要,它让subscribe只监听count的变化,避免每次state里任意字段变化都触发回调,性能上会好很多。

如果你想同时监听多个字段,比如count和name,可以写成{ path: ['count', 'name'] }

另外提一嘴,你如果直接用snap.count做依赖不行,但Valtio 2.x支持了解构语法const { count } = snap这样是响应式的,你可以试试。不过副作用监听还是用subscribe更直观。
点赞
2026-03-17 16:02