Adding flavor to @Daniel 's answer.
This is exactly what I'm struggling with regarding to best practices ATM and came to some conclusions:
Pulling the Ref outside of the composition fn would fix your problem but if you think about it, it's like sharing a single instance of a data property used in multiple places. You should be very careful with this, since ref is mutable for whoever pulls it, and will easily break unidirectional data flow.
For e.g. sharing a single Ref instance between a parent component and a child components can be compared to passing it down from parent's data to child's props, and as I assume we all know we should avoid mutating props directly
So classical answer for your question would be, move it to Vuex state and read it from there.
But if you have a small application, don't want a state manager, or simply want to take full advantage of the composition API, then my suggestion would be to at least do something of this pattern
import { ref, computed } from "vue";
const _searchPin = ref(""); // Mutable persistant prop
const searchPin = computed(() => _searchPin.value); // Readonly computed prop to expose
export default function useSearch() {
function searchResults() {
return searchPin.value;
}
return {
searchPin,
searchResults
};
}
Not more than ONE component should mutate the persistent Ref while others could only listen to the computed one.
If you find that more than one component needs access to change the ref, then that's probably a sign you should find another way to implement this (Vuex, props and events, etc...)
As I said, I am still trying to make sense of this myself and am not sure this is a good enough pattern either, but it's definitely better then simply exposing the instance.
Another option for code arrangement would be to encapsulate in 2 different access hooks
import { ref, readonly } from "vue";
const searchPin = ref(""); // Mutable persistant prop
export const useSearchSharedLogic() {
return readonly({
searchPin
})
}
const useSearchWriteLogic() {
return {
searchPin
}
}
// ----------- In another file -----------
export default function useSearch() {
const { searchPin } = useSearchSharedLogic()
function searchResults() {
return searchPin.value;
}
return {
searchPin,
searchResults
};
}
Or something of this sort (Not even sure this would work correctly as written).
Point is, don't expose a single instance directly
Another point worth mentioning is that this answer takes measure to preserve unidirectional data flow pattern. Although this is a basic proven pattern for years, it's not carved in stone. As composition patterns get clearer in the close time, IMO we might see people trying to challenge this concept and returning in some sense to bidirectional pattern like in Angular 1, which at the time caused many problems and wasn't implemented well