Skip to content

Commit 12ec71f

Browse files
committed
Merge remote-tracking branch 'origin/main' into powersync-sqlite-core-030
2 parents a51b1d9 + 8047546 commit 12ec71f

File tree

19 files changed

+5474
-4109
lines changed

19 files changed

+5474
-4109
lines changed

.changeset/smart-jobs-change.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ docs/react-native-sdk/
2323
docs/react-sdk/
2424
docs/vue-sdk/
2525
docs/web-sdk/
26+
docs/tanstack-react-query-sdk
2627

2728
.env

docs/utils/packageMap.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ enum Packages {
55
ReactSdk = 'react-sdk',
66
VueSdk = 'vue-sdk',
77
AttachmentsSdk = 'attachments-sdk',
8-
WebSdk = 'web-sdk'
8+
WebSdk = 'web-sdk',
9+
TanstackReactQuerySdk = 'tanstack-react-query-sdk'
910
}
1011

1112
interface Package {
@@ -55,5 +56,12 @@ export const packageMap: PackageMap = {
5556
entryPoints: ['../packages/web/src/index.ts'],
5657
tsconfig: '../packages/web/tsconfig.json',
5758
id: Packages.WebSdk
59+
},
60+
[Packages.TanstackReactQuerySdk]: {
61+
name: 'Tanstack React Query SDK',
62+
dirName: Packages.TanstackReactQuerySdk,
63+
entryPoints: ['../packages/tanstack-react-query/src/index.ts'],
64+
tsconfig: '../packages/tanstack-react-query/tsconfig.json',
65+
id: Packages.TanstackReactQuerySdk
5866
}
5967
};

packages/react-native/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# @powersync/react-native
22

3+
## 1.12.4
4+
5+
### Patch Changes
6+
7+
- Updated dependencies [f8ac369]
8+
- @powersync/react@1.4.5
9+
310
## 1.12.3
411

512
### Patch Changes

packages/react-native/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@powersync/react-native",
3-
"version": "1.12.3",
3+
"version": "1.12.4",
44
"publishConfig": {
55
"registry": "https://registry.npmjs.org/",
66
"access": "public"

packages/react/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# @powersync/react
22

3+
## 1.4.5
4+
5+
### Patch Changes
6+
7+
- f8ac369: Ensuring that `useQuery`'s `isFetching` becomes true immediately after the query changes.
8+
39
## 1.4.4
410

511
### Patch Changes

packages/react/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@powersync/react",
3-
"version": "1.4.4",
3+
"version": "1.4.5",
44
"publishConfig": {
55
"registry": "https://registry.npmjs.org/",
66
"access": "public"

packages/react/src/hooks/useQuery.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,33 @@ export const useQuery = <T = any>(
6666
const memoizedOptions = React.useMemo(() => options, [JSON.stringify(options)]);
6767
const abortController = React.useRef(new AbortController());
6868

69+
const previousQueryRef = React.useRef({ sqlStatement, memoizedParams });
70+
71+
// Indicates that the query will be re-fetched due to a change in the query.
72+
// Used when `isFetching` hasn't been set to true yet due to React execution.
73+
const shouldFetch = React.useMemo(
74+
() =>
75+
previousQueryRef.current.sqlStatement !== sqlStatement ||
76+
JSON.stringify(previousQueryRef.current.memoizedParams) != JSON.stringify(memoizedParams),
77+
[powerSync, sqlStatement, memoizedParams, isFetching]
78+
);
79+
6980
const handleResult = (result: T[]) => {
81+
setData(result);
7082
setIsLoading(false);
7183
setIsFetching(false);
72-
setData(result);
7384
setError(undefined);
85+
previousQueryRef.current = { sqlStatement, memoizedParams };
7486
};
7587

7688
const handleError = (e: Error) => {
89+
setData([]);
7790
setIsLoading(false);
7891
setIsFetching(false);
79-
setData([]);
8092
const wrappedError = new Error('PowerSync failed to fetch data: ' + e.message);
8193
wrappedError.cause = e;
8294
setError(wrappedError);
95+
previousQueryRef.current = { sqlStatement, memoizedParams };
8396
};
8497

8598
const fetchData = async () => {
@@ -139,5 +152,5 @@ export const useQuery = <T = any>(
139152
};
140153
}, [powerSync, sqlStatement, memoizedParams, memoizedOptions, tables]);
141154

142-
return { isLoading, isFetching, data, error, refresh: fetchData };
155+
return { isLoading, isFetching: isFetching || shouldFetch, data, error, refresh: fetchData };
143156
};

packages/react/tests/useQuery.test.tsx

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as commonSdk from '@powersync/common';
2-
import { renderHook, waitFor } from '@testing-library/react';
2+
import { cleanup, renderHook, waitFor } from '@testing-library/react';
33
import React from 'react';
4-
import { afterEach, describe, expect, it, vi } from 'vitest';
4+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
55
import { PowerSyncContext } from '../src/hooks/PowerSyncContext';
66
import { useQuery } from '../src/hooks/useQuery';
77

@@ -12,16 +12,17 @@ const mockPowerSync = {
1212
})),
1313
resolveTables: vi.fn(() => ['table1', 'table2']),
1414
onChangeWithCallback: vi.fn(),
15-
getAll: vi.fn(() => ['list1', 'list2'])
15+
getAll: vi.fn(() => Promise.resolve(['list1', 'list2']))
1616
};
1717

1818
vi.mock('./PowerSyncContext', () => ({
1919
useContext: vi.fn(() => mockPowerSync)
2020
}));
2121

2222
describe('useQuery', () => {
23-
afterEach(() => {
24-
vi.resetAllMocks();
23+
beforeEach(() => {
24+
vi.clearAllMocks();
25+
cleanup(); // Cleanup the DOM after each test
2526
});
2627

2728
it('should error when PowerSync is not set', async () => {
@@ -48,14 +49,14 @@ describe('useQuery', () => {
4849
);
4950

5051
const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
51-
const currentResult = result.current;
52-
expect(currentResult.isLoading).toEqual(true);
52+
expect(result.current.isLoading).toEqual(true);
5353

54-
waitFor(
54+
await waitFor(
5555
async () => {
56-
expect(currentResult.isLoading).toEqual(false);
56+
const currentResult = result.current;
5757
expect(currentResult.data).toEqual(['list1', 'list2']);
5858
expect(currentResult.isLoading).toEqual(false);
59+
expect(currentResult.isFetching).toEqual(false);
5960
expect(mockPowerSync.onChangeWithCallback).not.toHaveBeenCalled();
6061
expect(mockPowerSync.getAll).toHaveBeenCalledTimes(1);
6162
},
@@ -69,13 +70,14 @@ describe('useQuery', () => {
6970
);
7071

7172
const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
72-
const currentResult = result.current;
73-
expect(currentResult.isLoading).toEqual(true);
73+
74+
expect(result.current.isLoading).toEqual(true);
7475

7576
let refresh;
7677

77-
waitFor(
78+
await waitFor(
7879
async () => {
80+
const currentResult = result.current;
7981
refresh = currentResult.refresh;
8082
expect(currentResult.isLoading).toEqual(false);
8183
expect(mockPowerSync.getAll).toHaveBeenCalledTimes(1);
@@ -105,11 +107,10 @@ describe('useQuery', () => {
105107
);
106108

107109
const { result } = renderHook(() => useQuery('SELECT * from lists', [], { runQueryOnce: true }), { wrapper });
108-
const currentResult = result.current;
109110

110-
waitFor(
111+
await waitFor(
111112
async () => {
112-
expect(currentResult.error).toEqual(Error('PowerSync failed to fetch data: some error'));
113+
expect(result.current.error).toEqual(Error('PowerSync failed to fetch data: some error'));
113114
},
114115
{ timeout: 100 }
115116
);
@@ -133,11 +134,10 @@ describe('useQuery', () => {
133134
);
134135

135136
const { result } = renderHook(() => useQuery('SELECT * from lists', []), { wrapper });
136-
const currentResult = result.current;
137137

138-
waitFor(
138+
await waitFor(
139139
async () => {
140-
expect(currentResult.error).toEqual(Error('PowerSync failed to fetch data: some error'));
140+
expect(result.current.error).toEqual(Error('PowerSync failed to fetch data: some error'));
141141
},
142142
{ timeout: 100 }
143143
);
@@ -173,13 +173,13 @@ describe('useQuery', () => {
173173
});
174174
});
175175

176-
// The test returns unhandled errors when run with all the others.
177-
// TODO: Fix the test so that there are no unhandled errors (this may be a vitest or @testing-library/react issue)
178-
it.skip('should show an error if parsing the query results in an error', async () => {
176+
it('should show an error if parsing the query results in an error', async () => {
179177
const wrapper = ({ children }) => (
180178
<PowerSyncContext.Provider value={mockPowerSync as any}>{children}</PowerSyncContext.Provider>
181179
);
182-
vi.spyOn(commonSdk, 'parseQuery').mockReturnValue(Error('error') as any);
180+
vi.spyOn(commonSdk, 'parseQuery').mockImplementation(() => {
181+
throw new Error('error');
182+
});
183183

184184
const { result } = renderHook(
185185
() =>
@@ -189,10 +189,10 @@ describe('useQuery', () => {
189189
}),
190190
{ wrapper }
191191
);
192-
const currentResult = result.current;
193192

194-
waitFor(
193+
await waitFor(
195194
async () => {
195+
const currentResult = result.current;
196196
expect(currentResult.isLoading).toEqual(false);
197197
expect(currentResult.isFetching).toEqual(false);
198198
expect(currentResult.data).toEqual([]);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# @powersync/tanstack-react-query
2+
3+
## 0.0.1
4+
5+
### Patch Changes
6+
7+
- c4e183a: Initial Alpha version.

0 commit comments

Comments
 (0)