Skip to content

Commit cf75702

Browse files
authored
fix: vue 2 support for provideLocal and injectLocal (#3464)
1 parent 90d3400 commit cf75702

File tree

5 files changed

+112
-28
lines changed

5 files changed

+112
-28
lines changed
Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,54 @@
1-
import { type InjectionKey, type Ref, defineComponent, h, inject, ref } from 'vue-demi'
2-
import { createInjectionState } from '@vueuse/shared'
1+
import { type InjectionKey, type Ref, defineComponent, h, inject, nextTick, ref } from 'vue-demi'
2+
import { createInjectionState, injectLocal } from '@vueuse/shared'
33
import { describe, expect, it } from 'vitest'
4-
import { mount } from '../../.test'
4+
import { mount, useSetup } from '../../.test'
55

66
describe('createInjectionState', () => {
7-
it('should work 1', () => {
7+
it('should work for simple nested component', async () => {
88
const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => {
99
const count = ref(initialValue)
1010
return count
1111
})
1212

13+
let count: Ref<number> | undefined
14+
1315
const ChildComponent = defineComponent({
1416
setup() {
15-
const count = useCountState()
16-
expect(count?.value).toBe(0)
17+
count = useCountState()
1718

1819
return () => h('div')
1920
},
2021
})
2122

2223
const RootComponent = defineComponent({
2324
setup() {
24-
useProvideCountState(0)
25+
useProvideCountState(114514)
2526

2627
return () => h(ChildComponent)
2728
},
2829
})
2930

30-
mount(RootComponent)
31+
const vm = mount(RootComponent)
32+
await nextTick()
33+
34+
expect(count?.value).toBe(114514)
35+
vm.unmount()
3136
})
3237

33-
it('should work (custom key)', () => {
38+
it('should work for custom key', async () => {
3439
const KEY: InjectionKey<Ref<number>> = Symbol('count-state')
3540

3641
const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => {
3742
const count = ref(initialValue)
3843
return count
3944
}, { injectionKey: KEY })
4045

46+
let count: Ref<number> | undefined
47+
let count2: Ref<number> | undefined
4148
const ChildComponent = defineComponent({
4249
setup() {
43-
const count = useCountState()
44-
expect(count?.value).toBe(0)
45-
const count2 = inject(KEY)
46-
expect(count2?.value).toBe(0)
50+
count = useCountState()
51+
count2 = inject(KEY)
4752

4853
return () => h('div')
4954
},
@@ -57,25 +62,43 @@ describe('createInjectionState', () => {
5762
},
5863
})
5964

60-
mount(RootComponent)
65+
const vm = mount(RootComponent)
66+
await nextTick()
67+
expect(count?.value).toBe(0)
68+
expect(count2?.value).toBe(0)
69+
vm.unmount()
6170
})
6271

63-
it('allow call provideLocal and injectLocal in same component', () => {
72+
it('allow call useProvidingState and useInjectedState in same component', async () => {
6473
const [useProvideCountState, useCountState] = createInjectionState((initialValue: number) => {
6574
const count = ref(initialValue)
6675
return count
6776
})
77+
const vm = useSetup(() => {
78+
useProvideCountState(114514)
79+
const count = useCountState()!
6880

69-
const CanProvidingStateAndInjectedStateInSameComponent = defineComponent({
70-
setup() {
71-
useProvideCountState(114514)
72-
const count = useCountState()!
73-
expect(count.value).toBe(114514)
74-
75-
return () => h('div')
76-
},
81+
return { count }
7782
})
83+
await nextTick()
84+
expect(vm.count).toBe(114514)
85+
vm.unmount()
86+
})
7887

79-
mount(CanProvidingStateAndInjectedStateInSameComponent)
88+
it('allow call useProvidingState and injectLocal in same component', async () => {
89+
const KEY: InjectionKey<Ref<number>> | string = Symbol('count-state')
90+
const [useProvideCountState] = createInjectionState((initialValue: number) => {
91+
const count = ref(initialValue)
92+
return count
93+
}, { injectionKey: KEY })
94+
const vm = useSetup(() => {
95+
useProvideCountState(114514)
96+
const count = injectLocal(KEY)!
97+
98+
return { count }
99+
})
100+
await nextTick()
101+
expect(vm.count).toBe(114514)
102+
vm.unmount()
80103
})
81104
})
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { type InjectionKey, defineComponent, getCurrentInstance, h, nextTick } from 'vue-demi'
2+
import { injectLocal, provideLocal } from '@vueuse/shared'
3+
import { describe, expect, it } from 'vitest'
4+
import { mount, useSetup } from '../../.test'
5+
6+
describe('provideLocal injectLocal deps', () => {
7+
it('depends on getCurrentInstance().proxy === getCurrentInstance().proxy', async () => {
8+
const vm = useSetup(() => {
9+
const instance1 = getCurrentInstance()
10+
const instance2 = getCurrentInstance()
11+
const instanceProxyStable = instance1?.proxy === instance2?.proxy
12+
return { instance1, instance2, instanceProxyStable }
13+
})
14+
await nextTick()
15+
expect(vm.instance1).not.toBeNull()
16+
expect(vm.instance2).not.toBeNull()
17+
expect(vm.instance1).toBeTypeOf('object')
18+
expect(vm.instance2).toBeTypeOf('object')
19+
expect(vm.instanceProxyStable).toBe(true)
20+
vm.unmount()
21+
})
22+
})
23+
24+
describe('provideLocal injectLocal', () => {
25+
it('should work for nested component', async () => {
26+
const CountKey: InjectionKey<number> | string = Symbol('count')
27+
let count: number | undefined
28+
const ChildComponent = defineComponent({
29+
setup() {
30+
count = injectLocal(CountKey)
31+
32+
return () => h('div')
33+
},
34+
})
35+
36+
const RootComponent = defineComponent({
37+
setup() {
38+
provideLocal(CountKey, 2333)
39+
40+
return () => h(ChildComponent)
41+
},
42+
})
43+
const vm = mount(RootComponent)
44+
await nextTick()
45+
46+
expect(count).toBe(2333)
47+
vm.unmount()
48+
})
49+
50+
it('should work for same component', async () => {
51+
const CountKey: InjectionKey<number> | string = Symbol('count')
52+
const vm = useSetup(() => {
53+
provideLocal(CountKey, 2333)
54+
const count = injectLocal(CountKey)!
55+
return { count }
56+
})
57+
await nextTick()
58+
expect(vm.count).toBe(2333)
59+
vm.unmount()
60+
})
61+
})

packages/shared/injectLocal/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import { localProvidedStateMap } from '../provideLocal/map'
1313
// @ts-expect-error overloads are not compatible
1414
export const injectLocal: typeof inject = (...args) => {
1515
const key = args[0] as string | symbol
16-
const instance = getCurrentInstance()
16+
const instance = getCurrentInstance()?.proxy
1717
if (instance == null)
18-
throw new Error('injectEnhancedAllowanceOfCallsFromTheSameComponent must be called in setup')
18+
throw new Error('injectLocal must be called in setup')
1919

2020
if (localProvidedStateMap.has(instance) && key in localProvidedStateMap.get(instance)!)
2121
return localProvidedStateMap.get(instance)![key]

packages/shared/provideLocal/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { localProvidedStateMap } from './map'
1111
* ```
1212
*/
1313
export const provideLocal: typeof provide = (key, value) => {
14-
const instance = getCurrentInstance()
14+
const instance = getCurrentInstance()?.proxy
1515
if (instance == null)
1616
throw new Error('provideLocal must be called in setup')
1717

packages/shared/provideLocal/map.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
import type { getCurrentInstance } from 'vue-demi'
22

3-
export const localProvidedStateMap = new WeakMap<NonNullable<ReturnType<typeof getCurrentInstance>>, Record<string | symbol, any>>()
3+
export const localProvidedStateMap = new WeakMap<NonNullable<NonNullable<ReturnType<typeof getCurrentInstance>>['proxy']>, Record<string | symbol, any>>()

0 commit comments

Comments
 (0)