【Vue】リアクティブ変数初期化順序によるwatchEffectの挙動変化
はじめに
watchEffectに記述した内容が意図しない挙動をしていたので調べた備忘録です。
watchEffect
とリアクティブな変数の初期化順序について
watchEffect
はリアクティブな変数の変更を監視し、変更があった場合にコールバック関数を呼び出す機能を持っています。しかし、watchEffect
が呼び出されるタイミングはリアクティブな変数が初期化される前でも後でもあり得ます。このため、変数の初期化が完了する前にwatchEffect
が呼び出された場合、その時点では変数はまだ初期化されていないため、undefinedやnullなどの予期しない値を使用することになります。
例えば、以下のようにwatchEffectでリアクティブ変数を監視するとします。
import { reactive, watchEffect } from 'vue'
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(state.count)
})
state.count++
この場合、watchEffect
のコールバック関数が呼び出される順序は、リアクティブな変数が初期化される前でも後でも構いません。つまり、リアクティブな変数state
が初期化される前にwatchEffect
が呼び出された場合、コンソールにはundefined
が出力されます。一方、state
が初期化された後にwatchEffect
が呼び出された場合、state.count
の値が出力されます。
このように、リアクティブな変数が初期化される前にwatchEffect
が呼び出されると、初期値が未定義であるため、watchEffect
のコールバック関数で意図しない結果が返される可能性があります。
watchEffect
を使用する際の注意点
初期化前の変数を使用する場合、以下のような問題が発生する可能性があります。
- リアクティブな変数が初期化される前にwatchEffectが呼び出されるため、変数の初期値が未定義である場合、エラーが発生する可能性があります。
- リアクティブな変数が初期化される前にwatchEffectが呼び出されるため、変数の初期値を使用して意図しない動作が発生する可能性があります。
watchEffect
でリアクティブな変数を使う方法
watchEffect
を使用する場合は、リアクティブな変数が初期化された後に呼び出されるようにする必要があります。初期化前の変数を使用する場合は、初期化後に値を再設定するか、watchEffect
の代わりにwatch
やcomputed
を使用した方が良いです。
リアクティブな変数が初期化された後に呼び出されるようにするためには、以下のような方法が考えられます。
setup()
関数の中で使用する
setup()
関数は、コンポーネントが初期化される前に呼び出されるため、リアクティブな変数が初期化された後にwatchEffect
を使用することができます。
import { reactive, watchEffect } from 'vue'
export default {
setup() {
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(state.count)
})
return {
state
}
}
}
onMounted()
フックで使用する
onMounted()
フックは、コンポーネントがマウントされた後に呼び出されるため、リアクティブな変数が初期化された後にwatchEffect
を使用することができます。
import { reactive, watchEffect, onMounted } from 'vue'
export default {
setup() {
const state = reactive({
count: 0
})
onMounted(() => {
watchEffect(() => {
console.log(state.count)
})
})
return {
state
}
}
}
これらの方法を使用することで、リアクティブな変数が初期化された後にwatchEffectを呼び出すことができます。初期化前の変数を使用しないように注意して使いましょう💦
まとめ
以上、述べてきたようにwatchEffect
を使用する際に、初期化前の変数を使用すると意図しない動作を引き起こす可能性があります。そのため、リアクティブな変数が初期化された後にwatchEffect
を呼び出すことが重要です!
参考文献
Discussion