Search code examples
vue.jsvuejs3vue-component

How to use a ref in two different components in Vuejs


i have two components (Title and Input components) that should have the same title ref and when one is changed the other should also change. i tried what i did understand from this replies in this discussion but it didn't work. what i am missing?

Home.vue:

<template>
  <Title></Title>
  <Input></Input>
</template>

<script setup>
import Input from '../Components/Input.vue';
import Title from '../Components/Title.vue';
</script>

Title.vue:

<template>
  <h1 class="text-4xl font-bold">{{ title }}</h1>
</template>

<script setup>
import useTitles from '../composables/titles';

const { title } = useTitles();
</script>

Input.vue:

<template>
  <input type="text" v-model="title">
  <button @click="change">submit</button>
</template>

<script setup>
import useTitles from '../composables/titles';

const { title } = useTitles();

const change = () => {
  title.value = 'title changed'
}

</script>

titles.js:

import { ref } from 'vue'

export default function useTitles() {
  const title = ref('Home')

  return { title }
}

Solution

  • Composable functions don't work in an exceptional way themselves, it's the same as unwrapping the function, i.e. evaluating ref('Home') in each of these components, this results in title state not being shared between them.

    If the intention is to share the state, it should be either global state:

    // titles.js
    export const title = ref('Home')
    

    Or if there can be multiple states per app, the state needs to be provided to component hierarchy with provide/inject:

    // Home.vue
    const title = ref('Home')
    provide('title', title)
    
    // Title.vue
    const title = inject('title')