VuReact is a tool that compiles Vue 3 code into standard, maintainable React code. In this article, we will look at another frequently used Vue API: watchEffect().
If you write watchEffect() in Vue, what does VuReact generate on the React side?
Before We Start
To keep the examples easy to read, this article follows two simple conventions:
- All Vue and React snippets focus on core logic only, with full component wrappers and unrelated configuration omitted.
- The discussion assumes you are already familiar with the API shape and core behavior of Vue 3
watchEffect.
Compilation Mapping
Vue watchEffect() -> React useWatchEffect()
watchEffect() is Vue 3's API for running side effects that automatically track their reactive dependencies during execution.
VuReact compiles that pattern into useWatchEffect(), and during compilation it can statically analyze the reactive reads inside the effect and generate the matching React dependency array for you.
- Vue
<script setup>
import { ref, watchEffect } from 'vue';
const count = ref(0);
watchEffect(() => {
console.log(`Current count: ${count.value}`);
});
</script>
- Compiled React
import { useVRef, useWatchEffect } from '@vureact/runtime-core';
const count = useVRef(0);
useWatchEffect(() => {
console.log(`Current count: ${count.value}`);
}, [count.value]);
As the example shows, Vue watchEffect() is compiled into useWatchEffect().
VuReact's useWatchEffect is the runtime adapter for watchEffect(). It preserves the expected Vue-style behavior, including automatic dependency collection, cleanup handling, and stop control.
Just as importantly, VuReact analyzes the effect body during compilation and generates the dependency array automatically, so developers do not have to maintain it by hand.
Vue watchEffect() with flush -> React useWatchPostEffect() / useWatchSyncEffect()
Vue also lets watchEffect() control timing through the flush option. VuReact preserves that timing model by compiling different flush modes into the corresponding React-side runtime APIs.
- Vue
<script setup>
import { ref, watchEffect } from 'vue';
const width = ref(0);
const elRef = ref(null);
watchEffect(
() => {
if (elRef.value) {
width.value = elRef.value.offsetWidth;
}
},
{ flush: 'post' },
);
watchEffect(
() => {
console.log(elRef.value);
},
{ flush: 'sync' },
);
</script>
- Compiled React
import { useVRef, useWatchPostEffect, useWatchSyncEffect } from '@vureact/runtime-core';
const width = useVRef(0);
const elRef = useVRef(null);
useWatchPostEffect(
() => {
if (elRef.value) {
width.value = elRef.value.offsetWidth;
}
},
[elRef.value, width.value, elRef.value?.offsetWidth],
);
useWatchSyncEffect(
() => {
console.log(elRef.value);
},
[elRef.value],
);
VuReact analyzes the dependencies used inside each effect and generates the dependency arrays needed to preserve the expected behavior of useWatchEffect(), useWatchPostEffect(), and useWatchSyncEffect().
Related Links
Repository: https://github.com/vureact-js/core
VuReact docs: https://vureact.top/en/guide/semantic-comparison/script/watch-effect.html
Runtime docs: https://runtime.vureact.top/en/guide/introduction.html
Top comments (0)