Continuing with the composable pattern, one improvement we can add is to allow the arguments to be flexible, meaning they can be reactive or non-reactive values. This makes your composable even more reusable.
How to achieve this? Thanks to the functions ref
, unref
, and isRef
.
ref
Vue 3 reactivty API allows you to create reactive values either inside or outside a component (in a composable, for
instance). When creating a reactive reference with ref
, it returns an object with the original value stored in
the value
property, which is always up to date. For example:
const name = ref("Juan")
name.value // Juan
name.value += " Andrés"
name.value // Juan Andrés
unref
This function returns the internal value stored in value
if a reactive reference is passed to it. Otherwise (if it's
not a reactive reference), it returns the argument as is.
const name = ref("Juan")
const myName = unref(name) // retorna name.value
myName // Juan
const newName = unref(myName)
newName // Juan
isRef
Another useful utility is the isRef
function, which returns a boolean value indicating whether a value is a reactive
reference or not.
const name = ref("Juan")
isRef(name) // true
Understanding this, how do we apply it to a composable?
Making useAsync
Flexible
Let's enable our useAsync
composable to accept an API_URL
that can be either a static (string) or a reactive
reference. The advantage of the second option is that we can react to changes in its value.
Below, I will embed the code for you to test, but essentially there are two important changes.
Firstly, we use unref
to make the HTTP request to fetch the data. This way, we obtain the string with the URL, whether
it's a reactive reference or not.
const { results: users } = await (await fetch(unref(API_URL))).json();
The second change involves using isRef
to determine if we can observe changes in API_URL
and then retrigger the
request using makeRequest
.
if (isRef(API_URL)) {
watchEffect(makeRequest);
} else {
makeRequest();
}
Now, you can change the URL to query and observe how the results are updated:
setInterval(() => {
const randomNumber = Math.floor(Math.random() * 10) + 1;
API_URL.value = 'https://randomuser.me/api/?results=' + randomNumber;
}, 2000);
Conclusion
Use
isRef
andunref
to create reusable code (not just composables) that can work with reactive values (created withref
) or static values (strings, numbers, etc).