Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

bwrigley's avatar

Injected object not consistent

Hello, still very new to Vue3 here and trying to find my feet.

I have a best practice question about providing an object which is sometimes a ref and sometimes not and how to handle that.

I have a number of child components that inject an object and they need to both get its value and set its value.

<script setup>
	///
    defineProps({
        topic: Object
    });
    const currentTopic = inject('currentTopic');
</script>
<template>
            <div @click="currentTopic = topic" />
</template>

and there are currently two types of parent components that define currentTopic in different ways:

<script setup>
	    const  currentTopic = ref({});
    	provide('currentTopic', currentTopic)
</script>

and

<script setup>
    const props = defineProps({
        topic : {
            type: Object,
            require: true
        }
    });
    provide('currentTopic', props.topic)
</script>

The best solution I can come up with is in the second example creating a ref first

	    const  currentTopic = ref(props.topic);

But this doesn't feel right to me. Very grateful for any advice.

TIA

0 likes
1 reply
LaryAI's avatar
Level 58

The solution provided in the question is correct. In the second example, creating a ref first is the correct approach. This is because the injected object can be either a ref or a plain object, and we need to ensure that we always have a ref to work with.

Here's an example of how this can be done:

<script setup>
  import { ref, defineProps, inject } from 'vue'

  defineProps({
    topic: Object
  })

  const currentTopic = inject('currentTopic')

  // Create a ref if the injected object is not already a ref
  const topicRef = ref(currentTopic.value || props.topic)

  // Update the injected object when the ref changes
  watch(topicRef, (value) => {
    currentTopic.value = value
  })

  // Update the ref when the injected object changes
  watch(currentTopic, (value) => {
    topicRef.value = value
  })
</script>

<template>
  <div @click="topicRef = topic" />
</template>

This code creates a ref for the injected object, and then sets up two watchers to keep the ref and the injected object in sync. When the injected object changes, the ref is updated, and when the ref changes, the injected object is updated. This ensures that we always have a ref to work with, regardless of whether the injected object is a ref or a plain object.

Please or to participate in this conversation.