Skip to content

Commit fcb9d58

Browse files
authored
Fix useQuery race condition for initial query. (#525)
1 parent 7397bd9 commit fcb9d58

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

.changeset/slimy-glasses-jog.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@powersync/react': patch
3+
'@powersync/react-native': patch
4+
---
5+
6+
Fixed an issue with `useQuery` where initial query/parameter changes could cause a race condition if the first query took long.

packages/react/src/hooks/useQuery.ts

+21-7
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export type QueryResult<T> = {
2020
/**
2121
* Function used to run the query again.
2222
*/
23-
refresh?: () => Promise<void>;
23+
refresh?: (signal?: AbortSignal) => Promise<void>;
2424
};
2525

2626
/**
@@ -95,21 +95,31 @@ export const useQuery = <T = any>(
9595
setError(wrappedError);
9696
};
9797

98-
const fetchData = async () => {
98+
const fetchData = async (signal?: AbortSignal) => {
9999
setIsFetching(true);
100100
try {
101101
const result =
102102
typeof query == 'string' ? await powerSync.getAll<T>(sqlStatement, queryParameters) : await query.execute();
103+
104+
if (signal?.aborted) {
105+
return;
106+
}
107+
103108
handleResult(result);
104109
} catch (e) {
105110
console.error('Failed to fetch data:', e);
106111
handleError(e);
107112
}
108113
};
109114

110-
const fetchTables = async () => {
115+
const fetchTables = async (signal?: AbortSignal) => {
111116
try {
112117
const tables = await powerSync.resolveTables(sqlStatement, memoizedParams, memoizedOptions);
118+
119+
if (signal?.aborted) {
120+
return;
121+
}
122+
113123
setTables(tables);
114124
} catch (e) {
115125
console.error('Failed to fetch tables:', e);
@@ -118,9 +128,10 @@ export const useQuery = <T = any>(
118128
};
119129

120130
React.useEffect(() => {
131+
const abortController = new AbortController();
121132
const updateData = async () => {
122-
await fetchTables();
123-
await fetchData();
133+
await fetchTables(abortController.signal);
134+
await fetchData(abortController.signal);
124135
};
125136

126137
updateData();
@@ -129,7 +140,10 @@ export const useQuery = <T = any>(
129140
schemaChanged: updateData
130141
});
131142

132-
return () => l?.();
143+
return () => {
144+
abortController.abort();
145+
l?.();
146+
};
133147
}, [powerSync, memoizedParams, sqlStatement]);
134148

135149
React.useEffect(() => {
@@ -141,7 +155,7 @@ export const useQuery = <T = any>(
141155
powerSync.onChangeWithCallback(
142156
{
143157
onChange: async () => {
144-
await fetchData();
158+
await fetchData(abortController.current.signal);
145159
},
146160
onError(e) {
147161
handleError(e);

0 commit comments

Comments
 (0)