I use the onMounted + watchEffect for some expensive rendering
right now every time the app mounts the watchEffect function runs also
how can I run a function only when the app mounts
and prevent watchEffect run automatically --> only run it
after props value changes
// parent
<template>
<child :data="data" />
<button type="button" @click="changeData">click to change</button>
</template>
<script>
import Child from "./components/child.vue";
export default {
name: "App",
components: {
Child,
},
data() {
return {
data: [1],
};
},
methods: {
changeData() {
this.data = [1, 2];
},
},
};
</script>
// Child
<template>
<h1>I have this prop</h1>
</template>
<script>
import { onMounted, ref, watchEffect } from "@vue/runtime-core";
export default {
name: "Child",
props: ["data"],
setup(props) {
onMounted(() => {
// do this
watchEffect(() => {
// if props.data data changes do this
});
});
return {};
},
};
</script>
Not sure if I understand your question right, it should run, when the app mounts, but also not when it mounts?
Anyway, you can use watchEffect directly in the setup method, why nest it in the onMounted. And if you only want to listen to changes of the props, use just watch instead. watchEffect runs it once when it's mounted and then when any of the used props or refs are changed.
<template>
<h1>I have this prop</h1>
</template>
<script>
import { onMounted, watch, watchEffect } from "@vue/runtime-core";
export default {
name: "Child",
props: ["data"],
setup(props) {
onMounted(() => {
// do stuff once
});
watchEffect(() => {
// if mounted or if props.data data changes do this
});
watch(
() => props.data,
(data, prevData) => {
// if props.data data changes do this
}
);
return {};
},
};
</script>
One more suggestion added to Thomas answer is to use watchEffect with flush option as post
This will ensure that all your refs are also resolved
https://v3.vuejs.org/guide/reactivity-computed-watchers.html#effect-flush-timing
<template>
<h1>I have this prop</h1>
</template>
<script>
import { watchEffect, watchPostEffect } from "@vue/runtime-core";
export default {
name: "Child",
props: ["data"],
setup(props) {
watchEffect(() => {
// if mounted or if props.data data changes do this
}, { flush: 'post' });
// Vue 3.2+
watchPostEffect(() => {
// if mounted or if props.data data changes do this
});
return {};
},
};
</script>