状態管理ライブラリvaltioのメモ(Vanilla・小規模向け)
AstroでVue.js/Reactを使わない環境でvaltioをお試し中です。
状態の更新を従来のオブジェクト操作のように扱えるので親しみやすさがあって気に入っていますが、その一方で仕組みをちゃんと理解して使いこなすのに時間が掛かりそうだなとも感じました。
特に複数の状態をProxyオブジェクトでどうやって管理するのか、一つにまとめるのか複数に分割するのかなどが悩みどころなんですよね。
ちなみに、同作者の jotaiも使ってみたけど、こちらはシンプルに1つの状態を1つのAtomと呼ばれる単位で管理するので使い方で悩むことは特になかったです。
Vanilla・小規模向けという意味でも相性は良いですよね。
というわけで、使いこなせなかったらjotaiに移行することも視野に入れつつ、もう少しだけvaltioを試そうかなと思っています。
Vue.jsのリアクティビティーAPIとの比較も交えつつ不定期でメモしていきます。
Proxyオブジェクト
import { proxy } from 'valtio/vanilla'
const obj = { count: 0 }
const $state = proxy(obj)
$state.count++
valtioのproxy関数を呼び出すとProxyオブジェクトが返ってきます(Vue.jsのreactiveと同じですね)。
Proxyであることを除けば、渡したオブジェクトと表面的な構造は変わらないので、上記の例で言うとobjと$stateの型は同じになります。
これらについては、操作しようとしている対象がリアクティブなオブジェクトなのかが、直観的に分かりづらくはなりますね。
例えば、Vue.jsのRefであれば、
const $count = ref(0)
$countはRef<number>のような型になるので、IDEのツールチップなどで確認が簡単です。
今後、単にProxyオブジェクト
と表記してある場合は、valtioによってリアクティブな処理がされているものを指すこととします。
subscrbe
https://valtio.dev/docs/api/advanced/subscribe
import { proxy, subscribe } from 'valtio/vanilla'
const $states = proxy({ count1: 0, count2: 0 })
const unsubscribe = subscribe($states, () => {
console.log($states.count1, $states.count2)
})
$states.count1++
$states.count2++
// 監視停止
// unsubscribe()
// console.log(1, 1)
- 監視対象のProxyオブジェクトは1つだけ
- どのプロパティを変更してもコールバック関数は呼び出される
- 監視を停止するには
subscribe
の戻り値を使用する - デフォルトでは、コールバック関数の呼び出しは遅延されます
- 複数のプロパティが変更された場合、コールバック関数の呼び出しは1回にまとめられます
- プロパティ変更の直後に
unsubscribe
を実行すると、コールバック関数が呼び出される前に監視が停止されます
コールバック関数の非同期/同期呼び出し
第3引数によってコールバック関数の呼び出しタイミングを切り替えられます。
import { proxy, subscribe } from 'valtio/vanilla'
const $states = proxy({ count1: 0, count2: 0 })
const unsubscribe = subscribe(
$states,
() => {
console.log($states.count1, $states.count2)
},
true,
)
$states.count1++
// console.log(1, 0)
$states.count2++
// console.log(1, 1)
// 監視停止
unsubscribe()
第3引数をtrue
にすると、プロパティの変更があるたびにコールバック関数が呼び出されます。
上記の例では、コールバック関数が2回呼び出されてから監視が停止します。
入れ子のオブジェクト
入れ子のオブジェクトの一部だけを監視対象にすることもできます。
import { proxy, subscribe } from 'valtio/vanilla'
const $states = proxy({ count1: { value: 0 }, count2: { value: 0 } })
subscribe($states.count1, () => {
console.log($states.count1.value)
})
$states.count1.value++
上記の例では$states.count2.value
が変更されてもコールバック関数は呼び出されません。
subscribeKey
https://valtio.dev/docs/api/utils/subscribeKey
特定のプロパティのみを監視対象にできます。
これにより、不必要なコールバック関数呼び出しを避けることができます。
import { proxy } from 'valtio/vanilla'
import { subscribeKey } from 'valtio/vanilla/utils'
const $states = proxy({ count1: 0, count2: 0 })
const unsubscribeKey = subscribeKey($states, 'count1', () => {
console.log($states.count1)
})
// コールバック関数は呼び出される
$states.count1++
// コールバック関数は呼び出されない
// $states.count2++
// 監視停止
// unsubscribeKey()
個人的には、これがないとvaltioを使う理由がなくなってしまうぐらい重要な機能でした。
不必要なコールバック関数呼び出しを避けるためには、複数の状態に対してProxyオブジェクトを1つずつ用意することになり、結局はjotaiを使うのとあまり変わらなくなってしまうからですね。
watch
検証および執筆中