监控 store 内容变化
对于 store 中内容的变化的监控,Valtio 并没有限定必须在 React 组件中进行。而是在 React 组件内外都可以进行,不管在什么位置监控 store 内容的变化,都是使用 Valtio 提供的 subscribe
函数来完成的。
subscribe
函数的使用非常简单,只需要提供一个需要监控的被代理对象和一个被监控对象发生变化的时候需要执行的回调函数即可。subscribe
函数在执行以后会返回一个 unsubscribe
函数供解除订阅使用。例如以下代码即订阅了 store
的变化,并在其发生变化的时候输出其当前内容。
import { proxy, subscribe } from "valtio";
const store = proxy({
count: 0,
});
const unsubscribe = subscribe(store, (v) => {
console.log("store changed:", v);
});
store.count += 1;
store.count += 2;
unsubscribe();
因为 Valtio 会将被代理对象中的嵌套内容也进行代理,所以 subscribe
函数除了可以监控使用 proxy
函数创建的被代理对象以外,还可以监控被代理对象中的嵌套内容。
同时监控多个 store
subscribe
函数每次只能定义针对一个被代理对象的监控订阅。如果需要同时监控多个 store 的变化,那么使用 subscribe
就显得非常繁琐了。Valtio 在 valtio/utils
包中提供了一个 watch
方法,这个方法可以同时监控任意多个 store 的变化。
watch
函数只接受一个函数作为参数,这个函数拥有一个具名参数:get
。这个 get
参数是一个函数,可以通过调用 get
来将要被监控的 store 对象加入 watch
的监控列表中。同时,调用 get
以后,它会返回其参数中 store 的内容。
例如上一节中的 subscribe
使用 watch
来编写就是以下形式的。
import { watch } from "valtio/utils";
watch((get) => {
const state = get(store);
console.log("store changed:", state);
});
watch
函数的使用通常要比 subscribe
函数要灵活许多,建议在实际项目中有需要时可优先考虑使用。
wathc
函数同样也有其清理机制,但是并不像 subscribe
一样是返回一个清理函数,而是像 React 中的 useEffect
一样,在其中的回调函数中通过返回一个函数来实现清理。
在一般情况下,watch
函数对于被监控内容的变化是优化过的,如果连续变更被监控 store 中的内容,watch
仅会在 store 最后一次变更以后执行一次回调函数。如果需要 watch
在被监控的 store 每次发生变化的时候都执行回调函数,那么可以为 watch
函数附加一个内容为 {sync: ture}
的参数。
监控 store 中某一个属性的变化
例如当前有一个 store 如下:
const store = proxy({
count: 0,
content: "greetings",
});
如果现在只需要监控其中 count
属性的变化,在使用 subscribe
函数的时候,可以使用 subscribe(store.count, () => {})
的形式来实现。另外,在 valtio/utils
里还提供了一个 subscribrKey
函数,可以直接指定所需要监控的属性。
所以使用 subscribeKey
函数的时候上面的监控调用可以写成 subscribeKey(store, "count", () => {})
。