Skip to content

feat(reactivity): new function toShallowRef #8530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: minor
Choose a base branch
from
51 changes: 50 additions & 1 deletion packages/reactivity/__tests__/ref.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import {
toRefs,
} from '../src/index'
import { computed } from '@vue/runtime-dom'
import { customRef, shallowRef, triggerRef, unref } from '../src/ref'
import {
customRef,
shallowRef,
toShallowRef,
triggerRef,
unref,
} from '../src/ref'
import {
isReadonly,
isShallow,
Expand Down Expand Up @@ -454,3 +460,46 @@ describe('reactivity/ref', () => {
expect(spy).toHaveBeenCalledTimes(1)
})
})

describe('toShallowRef', () => {
it('should convert a function value to a Readonly Ref', () => {
const value = () => ({
a: 1,
})

const result = toShallowRef(value)

// @ts-expect-error
expect(() => (result.value = { b: 2 })).toThrow()
expect(result.value).toEqual(value())
})

it('should convert a Ref object value to a Ref', () => {
const value: Ref<number> = ref(42)
const result = toShallowRef(value)
expect(result === value).toBe(true)
})

it('should convert a regular value to a ShallowRef', () => {
const value = 'Hello World'
const result = toShallowRef(value)

expect(result.value).toEqual(value)
})

it('should convert object to a ShallowRef', () => {
const value = { a: 1 }
const result = toShallowRef(value)

let dummy
effect(() => {
dummy = result.value.a
})
expect(result.value).toEqual(value)
result.value.a = 2
expect(dummy).toEqual(1)

triggerRef(result)
expect(dummy).toEqual(2)
})
})
1 change: 1 addition & 0 deletions packages/reactivity/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
toRef,
toValue,
toRefs,
toShallowRef,
unref,
proxyRefs,
customRef,
Expand Down
29 changes: 29 additions & 0 deletions packages/reactivity/src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,35 @@ export function toRef(
}
}

/**
* Converts the given value to a shallow reference.
* @param value The value to be converted. It can be a function that returns a value, a Ref object, or a regular value.
* @returns The converted reference object. If the value is a function, it returns a Readonly<Ref<T>>.
* If the value is a Ref object, it returns a Ref<T>. Otherwise, it returns a ShallowRef<T>.
*/
export function toShallowRef<T>(value: () => T): Readonly<Ref<T>>

/**
* Converts the given value to a shallow reference.
* @param value The value to be converted. It can be a Ref object or a regular value.
* @returns The converted reference object. If the value is a Ref object, it returns a Ref<T>.
* Otherwise, it returns a ShallowRef<T>.
*/
export function toShallowRef<T>(value: Ref<T>): Ref<T>

/**
* Converts the given value to a shallow reference.
* @param value The value to be converted. It can be any type of value.
* @returns The converted reference object. If the value is a Ref object or a function that returns a value,
* it returns the corresponding reference object (Ref<T> or Readonly<Ref<T>>). Otherwise, it returns a ShallowRef<T>.
*/
export function toShallowRef<T>(value: T): ShallowRef<T>
export function toShallowRef<T>(value: unknown) {
return isRef(value) || typeof value === 'function'
? toRef(value)
: shallowRef(value)
}

function propertyToRef(
source: Record<string, any>,
key: string,
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export {
toRef,
toValue,
toRefs,
toShallowRef,
isProxy,
isReactive,
isReadonly,
Expand Down