Valtio里怎么监听某个状态的变化?
我用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 里某个属性的变化啊?
useSnapshot返回的是一个快照对象,虽然组件会因为快照的变化而重新渲染,但直接在useEffect的依赖数组里用snap.count并不会按预期工作。你需要用 Valtio 提供的subscribe方法来监听特定属性的变化。你可以这样做:
这样,当
state.count发生变化时,subscribe回调会被触发,你就可以在其中执行副作用操作了。记得返回unsubscribe函数以清理订阅。snap.count从Proxy对象里提取出来后就变成原始值了,useEffect的依赖数组根本检测不到变化。Valtio监听变化要用
subscribe,不是useEffect的依赖数组。正确写法:{ path: ['count'] }这个参数很重要,它让subscribe只监听count的变化,避免每次state里任意字段变化都触发回调,性能上会好很多。如果你想同时监听多个字段,比如count和name,可以写成
{ path: ['count', 'name'] }。另外提一嘴,你如果直接用
snap.count做依赖不行,但Valtio 2.x支持了解构语法const { count } = snap这样是响应式的,你可以试试。不过副作用监听还是用subscribe更直观。