Is there a way to share reactive data between random components in Vue 3 Composition API?

Viewed 1631

Having some reactive const in "Component A," which may update after some user action, how could this data be imported into another component? For example:

const MyComponent = {
      import { computed, ref } from "vue";
      setup() {
        name: "Component A",
        setup() {
          const foo = ref(null);
          
          const updateFoo = computed(() => foo.value = "bar");
          
          return { foo }
        }
      }
    }

Could the updated value of 'foo' be used in another Component without using provide/inject?

I am pretty new in the Vue ecosystem; kind apologies if this is something obvious that I am missing here.

1 Answers

One of the best things about composition API is that we can create reusable logic and use that all across the App. You create a composable functions in which you can create the logic and then import that into the components where you want to use it. Not only does this make your component much cleaner but also your APP much more maintainable. Below is a simple example of counter to show how they can be used. You can find working demo here:

Create a composable function for counter:

import { ref, computed } from "vue";
const counter = ref(0);
export const getCounter = () => {
  const incrementCounter = () => counter.value++;
  const decrementCounter = () => counter.value--;
  const counterPositiveOrNegitive = computed(() =>
    counter.value >= 0 ? " Positive" : "Negitive"
  );
  return {
    counter,
    incrementCounter,
    decrementCounter,
    counterPositiveOrNegitive
  };
};

Then you can import this function into your components and get the function or you want to use. Component to increment counter.

 <template>
  <div class="hello">
    <h1>Component To Increment Counter</h1>
    <button @click="incrementCounter">Increment</button>
  </div>
</template>

<script>
import { getCounter } from "../composables/counterExample";
export default {
  name: "IncrementCounter",
  setup() {
    const { incrementCounter } = getCounter();
    return { incrementCounter };
  },
};
</script>

Component to decrement counter:

<template>
  <div class="hello">
    <h1>Component To Decrement Counter</h1>
    <button @click="decrementCounter">Decrement</button>
  </div>
</template>

<script>
import { getCounter } from "../composables/counterExample";
export default {
  name: "DecrementCounter",
  setup() {
    const { decrementCounter } = getCounter();
    return { decrementCounter };
  },
};
</script>

Then in the main component, you can show the counter value.

<template>
  <img alt="Vue logo" src="./assets/logo.png" />
  <div class="counters">
    <IncrementCounter />
    <DecrementCounter />
  </div>
  <h3>Main Component </h3>
  <p>Counter: {{ counter }}</p>
  <p>{{ counterPositiveOrNegitive }}</p>
</template>

<script>
import IncrementCounter from "./components/IncrementCounter.vue";
import DecrementCounter from "./components/DecrementCounter.vue";
import { getCounter } from "./composables/counterExample";
export default {
  name: "App",
  components: {
    IncrementCounter: IncrementCounter,
    DecrementCounter: DecrementCounter,
  },
  setup() {
    const { counter, counterPositiveOrNegitive } = getCounter();
    return { counter, counterPositiveOrNegitive };
  },
};

Hope this was somewhat helpful. You can find a working example here:

https://codesandbox.io/s/vue3-composition-api-blfpj

Related