Closed shorwood closed 2 years ago
That feels a bit weird to me. When you want to pass value to the function, I think you'd better explicitly add .value
or the new ref sugar syntax. The case that reactify
trying to approach is the build the connections, when you give a function reactive input, it should give reactive output. I understand the motivation for unrefy
but I guess it might be a bit confusing to pass reactive data to a function that is supposed to be run once.
I agree. Furthermore, the example provided in the documentation is unrealistic. I hardly see unrefy
being used in a setup()
context. The function kinda goes against the principle of Vue's reactivity.
However unrefy
is meant to be sort of a shared function allowing cleaner integration with Vue-agnostic paradigms. I found it relatively useful when integrating external modules with Vue's Composition API, cleaning up composables, chaining wrappers while keeping types and implementing useful permissiveness.
import { updateMakeModel, Make } from '~/src/services/makes'
import { unrefy } from '@vueuse/shared'
import { partial } from 'lodash-es'
const make = ref('toyota')
/** Without unrefy */
const updateModel = (model: MaybeRef<string>, data: MaybeRef<Make>, options: MaybeRef<UpdateMakeOptions>) => updateMakeModel(unref(make), unref(model), unref(data), unref(options))
/** With unrefy */
const updateModel = partial(unrefy(updateMakeModel), make)
Here is an analogue of the context I used it in : Let's say, for the sake of the argument, that we have a small external library acting as an SDK and providing the functions below. They are all Vue-agnostic and they don't know what a Ref
is.
```ts /** Car manufacturer */ export interface Make { id: string, name: string, country: string, bankrupt: boolean models: string[] } /** Car model */ export interface Model { id: string, name: string, make: string year: number } /** Axios instance used to query */ const eventService = axios.create({baseURL: 'https://api.acme.com'}) /** Get a make from the API */ const getMake = async (make: string, params: GetMakeOptions): Make { return await eventService.get(`/makes/${make}`, { params }).then(res => res.data as Make) } /** Update a make in the API */ const updateMake = async (make: string, data: Make): Make { return await eventService.put(`/makes/${make}`, data).then(res => res.data as Make) } /** Remove a make from API */ const removeMake = async (make: string, data: Make) { return await eventService.delete(`/makes/${make}`).then(res => res.data) } /** Get model from a make from the API */ const getMakeModel = async (make: string, model: string, config: AxiosRequestConfig): Model { return await eventService.get(`/makes/${model}/${make}`, { params }).then(res => res.data as Model) } /** ... And few more utilities, you get the point. */ [...] ```
However, now we want to extend this SDK to make some composables out of it. We want a useMake
composable that allows the developer to easily manipulate car manufacturers and their models from the setup()
hook. We want the returned methods from useMake()
to allow a small degree of permissiveness in the arguments (they can be reactive or not). And we want to keep the types intact.
```ts
setup(props) {
/* ... */
//--- Init reactive variables.
const make: Ref
Now for the important part. Below are two implementation of useMake
, one with unrefy
and one without.
```ts
import { MaybeRef } from '@vueuse/shared'
import { unrefy } from '@vueuse/core'
import { partial } from 'lodash-es'
import {
getMake,
updateMake,
removeMake,
getMakeModel,
addMakeModel,
updateMakeModel,
removeMakeModel
} from '~/src/services/makes'
/** Composable for manipulation makes from the API . */
export const useMake = (
make: MaybeRef
```ts
import { MaybeRef } from '@vueuse/shared'
import {
getMake,
updateMake,
removeMake,
getMakeModel,
addMakeModel,
updateMakeModel,
removeMakeModel
} from '~/src/services/makes'
/** Composable for manipulation makes from the API . */
export const useMake = (
make: MaybeRef
I know this bit of a weird use case; But you can find a example of how it could be used from one of the sketchy projects i'm working on.
I see. But maybe the ref sugar could be a better solution for this? https://github.com/vuejs/rfcs/discussions/369
That would be one way to solve it. But would the RFC apply to legacy projects, the ones using @vue/composition-api
or @nuxtjs/composition-api
? You would have to explicitly install the correct version of @vue/compiler-sfc
, define refSugar: true
or refTransform: true
in the build config of these kind of projects.
Didn't know this existed. Well I guess i'll check that out. Thanks for the feedback.
Closed via #789
Hello everyone,
While on a project, i had to dynamically call functions but the arguments I called them with were sometimes
Ref
s. So my first thought was wrapping the function using thereactify
utility; But then I remembered the wrapped function returnsComputedRef<T>
and is evaluated on every changes of the arguments. And I want the function to only returnT
and only when I call it. I started looking for other utilities that might help and either did not found suitable one or did not search thoroughly enough.This is where
unrefy
comes from. Below is it's documentation entry.Pull Request : #789
Documentation
Convert a plain function into a function that unref it's aguments before every call. The converted function accepts refs and raw values as its arguments and returns the same value the unconverted function returns, with proper typing.
::: tip Make sure you're using the right tool for the job. Using
reactify
might be more pertinent in some cases where you want to evaluate the function on each changes of it's arguments. :::Usage
Related Functions
reactify
Source