WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 670740b

Browse files
committed
fix: watch for returned value changes
fixes: #46
1 parent 47904a7 commit 670740b

File tree

3 files changed

+96
-26
lines changed

3 files changed

+96
-26
lines changed

packages/core/src/useRouteQuery.ts

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { computed, Ref } from 'vue-demi';
1+
import { computed, reactive, Ref, watch } from 'vue-demi';
22

33
import { useRoute, useRouter } from './helpers';
44
import { queueQueryUpdate } from './queue-query-update';
55
import { RouteQueryTransformer } from './transformers';
66
import { RouteQuery } from './types';
7+
import { isObject } from './utils';
78

89
export function useRouteQuery(key: string, defaultValue: string): Ref<string>;
910
export function useRouteQuery(key: string, defaultValue: string | null): Ref<string | null>;
@@ -16,39 +17,60 @@ export function useRouteQuery<T>(key: string, defaultValue: T, transformer?: Rou
1617
queueQueryUpdate(router, route.value.query, key, newValue);
1718
}
1819

19-
return computed({
20-
get() {
21-
if (!(key in route.value.query)) {
22-
return defaultValue;
23-
}
20+
function get(): T {
21+
if (!(key in route.value.query)) {
22+
return defaultValue;
23+
}
2424

25-
const value = getQueryValue(route.value.query, key);
25+
const value = getQueryValue(route.value.query, key);
2626

27-
if (!value) {
28-
return defaultValue;
29-
}
27+
if (!value) {
28+
return defaultValue;
29+
}
3030

31-
if (!transformer) {
32-
// we know for sure that the value is a T (really a string) here if transformer is not provided
33-
return value as unknown as T;
34-
}
31+
if (!transformer) {
32+
// we know for sure that the value is a T (really a string) here if transformer is not provided
33+
return value as unknown as T;
34+
}
3535

36-
const transformedValue = transformer.fromQuery(value);
37-
if (transformedValue === undefined) {
38-
return defaultValue;
39-
}
36+
const transformedValue = transformer.fromQuery(value);
37+
if (transformedValue === undefined) {
38+
return defaultValue;
39+
}
40+
41+
return transformedValue;
42+
}
4043

41-
return transformedValue;
44+
function set(value: T) {
45+
if (!transformer) {
46+
// we know for sure that the value is a string or null here if transformer is not provided
47+
updateQueryParam(value as unknown as string | null);
48+
return;
49+
}
50+
51+
const transformedValue = transformer.toQuery(value ?? undefined);
52+
updateQueryParam(transformedValue);
53+
}
54+
55+
let valueWatchStopHandle: (() => void) | undefined;
56+
57+
return computed({
58+
get() {
59+
const value = get();
60+
if (isObject(value)) {
61+
const reactiveValue = reactive(value) as T & object;
62+
valueWatchStopHandle?.();
63+
valueWatchStopHandle = watch(reactiveValue, (newValue) => {
64+
set(newValue);
65+
});
66+
return reactiveValue;
67+
}
68+
return value;
4269
},
4370
set(value) {
44-
if (!transformer) {
45-
// we know for sure that the value is a string or null here if transformer is not provided
46-
updateQueryParam(value as unknown as string | null);
47-
return;
48-
}
71+
valueWatchStopHandle?.();
4972

50-
const transformedValue = transformer.toQuery(value ?? undefined);
51-
updateQueryParam(transformedValue);
73+
set(value);
5274
},
5375
});
5476
}

packages/core/src/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ export function removeEmptyValues<T extends Record<string, any>>(object: T): T {
88
function isEmpty(value: any): boolean {
99
return value === null || value === undefined || value === '';
1010
}
11+
12+
export function isObject(value: any): value is object {
13+
return typeof value === 'object' && value !== null;
14+
}

packages/tests-base/index.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,50 @@ export function testUseRouteQuery(
142142
expect(query.foo).toBe('FOO');
143143
expect(query.bar).toBe('BAR');
144144
});
145+
146+
it('should update query after changes in returned array', async () => {
147+
const transformer: RouteQueryTransformer<string[]> = {
148+
fromQuery(value: string): string[] | undefined {
149+
return value?.split(',');
150+
},
151+
toQuery(value: string[] | undefined): string | undefined {
152+
return value?.join(',');
153+
},
154+
};
155+
156+
const { result } = mountComposition(() => useRouteQuery('array', [], transformer));
157+
158+
result.value.push('foo');
159+
result.value.push('bar');
160+
await flushPromises();
161+
162+
expect(getCurrentQuery().array).toBe('foo,bar');
163+
164+
result.value = ['baz'];
165+
await flushPromises();
166+
167+
expect(getCurrentQuery().array).toBe('baz');
168+
});
169+
170+
it('should not react on returned array changes if it was reassigned', async () => {
171+
const transformer: RouteQueryTransformer<string[]> = {
172+
fromQuery(value: string): string[] | undefined {
173+
return value?.split(',');
174+
},
175+
toQuery(value: string[] | undefined): string | undefined {
176+
return value?.join(',');
177+
},
178+
};
179+
180+
const { result } = mountComposition(() => useRouteQuery('array', [], transformer));
181+
182+
const array = result.value;
183+
result.value = ['foo', 'bar'];
184+
array.push('baz');
185+
await flushPromises();
186+
187+
expect(getCurrentQuery().array).toBe('foo,bar');
188+
});
145189
}
146190

147191
function flushPromises(): Promise<void> {

0 commit comments

Comments
 (0)