0

My sample:

<script setup lang="ts">
import { onMounted, ref, watchEffect } from "vue";

const htmlRef = ref("ref");
const dataRef = ref({});

onMounted(() => {
  console.log("mount");
  // Init with htmlRef
});

watchEffect(() => {
  console.log("effect");
  // Run after dataRef change
});
</script>

<template>
  <div ref="ref"></div>
</template>

I have to integrate an external, pure JS chart with Vue.

  • In the init step, the library needs access to DOM, so it must be in onMounted(). This does NOT contain the initial render.
  • Whenever dataRef changes, the chart library needs to receive the whole dataRef and render again. Since watchEffect() runs eagerly, the initial render happens here naturally.

The only problem is that: init must be called before any render. Vue executes watchEffect() before onMounted(), so my code doesn't work at all. Now how should I structure my code?

My current solution:

  • Duplicate the render code. The initial render happens in onMounted(), and
  • Add a flag initialRender to skip initial render in watchEffect()

Is this idiomatic Vue? I came from React where marking initial render like this is considered bad practice.

1
  • 1
    Not sure if your library is tied to your state or just using the DOM, in the second case nextTick might be useful so that it's sure that your DOM has properly been updated before doing anything fancy with your charts. Commented May 3, 2024 at 10:29

1 Answer 1

1

watchEffect triggers immediately, not just before onMounted, this is the expected behaviour.

Either use watch without immediate flag:

watch(dataRef, data => ...)

Or don't use empty object that serves no purpose as initial state to make a clear distinction from an initialized value:

const dataRef = ref(null)
...
watchEffect(() => {
  if (!dataRef.value)
    return
...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.