Skip to content

Commit 3ddb6f2

Browse files
committed
refactor: replace queryClient prop with auto-detecting parent QueryClient
- Remove queryClient prop from StacApiProviderType - Detect parent via QueryClientContext instead of accepting prop - Update docs to show QueryClientProvider wrapping pattern - Document missing options and enableDevTools props in API reference This simplifies the API and prevents duplicate QueryClient instances.
1 parent 0b4bcdc commit 3ddb6f2

File tree

3 files changed

+62
-28
lines changed

3 files changed

+62
-28
lines changed

README.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ If you do not install it, your package manager will warn you, and stac-react wil
3535

3636
stac-react's hooks must be used inside children of a React context that provides access to the stac-react's core functionality.
3737

38-
To get started, initialize `StacApiProvider` with the base URL of the STAC catalog. `StacApiProvider` automatically sets up a [TanStack Query](https://tanstack.com/query/latest/docs/framework/react/overview) QueryClientProvider for you, so you do not need to wrap your app with QueryClientProvider yourself.
38+
To get started, initialize `StacApiProvider` with the base URL of the STAC catalog. `StacApiProvider` automatically sets up a [TanStack Query](https://tanstack.com/query/latest/docs/framework/react/overview) QueryClientProvider for you if one doesn't already exist in the component tree.
3939

4040
```jsx
4141
import { StacApiProvider } from 'stac-react';
@@ -47,19 +47,26 @@ function StacApp() {
4747
}
4848
```
4949

50-
If you want to provide your own custom QueryClient (for advanced caching or devtools), you can pass it as a prop:
50+
If you want to customize the QueryClient configuration (e.g., for custom caching behavior, retry logic, or global settings), wrap `StacApiProvider` with your own `QueryClientProvider`:
5151

5252
```jsx
5353
import { StacApiProvider } from 'stac-react';
54-
import { QueryClient } from '@tanstack/react-query';
54+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5555

56-
const queryClient = new QueryClient();
56+
const queryClient = new QueryClient({
57+
defaultOptions: {
58+
queries: {
59+
staleTime: 5 * 60 * 1000, // 5 minutes
60+
retry: 3,
61+
},
62+
},
63+
});
5764

5865
function StacApp() {
5966
return (
60-
<StacApiProvider apiUrl="https://my-stac-api.com" queryClient={queryClient}>
61-
{/* Other components */}
62-
</StacApiProvider>
67+
<QueryClientProvider client={queryClient}>
68+
<StacApiProvider apiUrl="https://my-stac-api.com">{/* Other components */}</StacApiProvider>
69+
</QueryClientProvider>
6370
);
6471
}
6572
```
@@ -110,9 +117,11 @@ function StacApp() {
110117

111118
##### Component Properties
112119

113-
| Option | Type | Description |
114-
| --------- | -------- | --------------------------------- |
115-
| `apiUrl`. | `string` | The base url of the STAC catalog. |
120+
| Option | Type | Description |
121+
| ---------------- | --------- | --------------------------------------------------------------------------------------------- |
122+
| `apiUrl` | `string` | The base url of the STAC catalog. |
123+
| `options` | `object` | Optional configuration object for customizing STAC API requests. |
124+
| `enableDevTools` | `boolean` | Optional. Enables TanStack Query DevTools browser extension integration. Defaults to `false`. |
116125

117126
### useCollections
118127

docs/react-query-setup.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,45 @@ stac-react relies on [TanStack Query](https://tanstack.com/query/latest/docs/fra
88
- Ensures your app and stac-react share the same QueryClient instance.
99
- Follows best practices for React libraries that integrate with popular frameworks.
1010

11-
stac-react manages the QueryClient for you by default, but you can provide your own for advanced use cases.
11+
## QueryClient Management
1212

13-
**Important:** If your app uses multiple providers that require a TanStack QueryClient (such as `QueryClientProvider` and `StacApiProvider`), always use the same single QueryClient instance for all providers. This ensures that queries, mutations, and cache are shared across your app and prevents cache fragmentation or duplicate network requests.
13+
By default, `StacApiProvider` automatically creates and manages a QueryClient for you if one doesn't already exist in the component tree. This means you can use stac-react without any additional setup:
1414

15-
**Example:**
15+
```jsx
16+
import { StacApiProvider } from 'stac-react';
17+
18+
function App() {
19+
return <StacApiProvider apiUrl="https://my-stac-api.com">{/* ...your app... */}</StacApiProvider>;
20+
}
21+
```
22+
23+
### Custom QueryClient Configuration
24+
25+
If you need custom QueryClient configuration (e.g., custom caching behavior, retry logic, or global settings), wrap `StacApiProvider` with your own `QueryClientProvider`:
1626

1727
```jsx
1828
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
1929
import { StacApiProvider } from 'stac-react';
2030

21-
const queryClient = new QueryClient();
31+
const queryClient = new QueryClient({
32+
defaultOptions: {
33+
queries: {
34+
staleTime: 5 * 60 * 1000, // 5 minutes
35+
retry: 3,
36+
},
37+
},
38+
});
2239

2340
function App() {
2441
return (
2542
<QueryClientProvider client={queryClient}>
26-
<StacApiProvider apiUrl="https://my-stac-api.com" queryClient={queryClient}>
27-
{/* ...your app... */}
28-
</StacApiProvider>
43+
<StacApiProvider apiUrl="https://my-stac-api.com">{/* ...your app... */}</StacApiProvider>
2944
</QueryClientProvider>
3045
);
3146
}
3247
```
3348

34-
If you do not pass the same QueryClient instance, each provider will maintain its own cache, which can lead to unexpected behavior.
49+
`StacApiProvider` will automatically detect the parent QueryClient and use it instead of creating a new one.
3550

3651
## TanStack Query DevTools Integration
3752

src/context/index.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
1-
import React, { useMemo, useState, useCallback } from 'react';
1+
import React, { useMemo, useState, useCallback, useContext } from 'react';
22
import { StacApiContext } from './context';
33
import type { CollectionsResponse, Item } from '../types/stac';
44
import { GenericObject } from '../types';
5-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5+
import { QueryClient, QueryClientProvider, QueryClientContext } from '@tanstack/react-query';
66

77
import useStacApi from '../hooks/useStacApi';
88

99
type StacApiProviderType = {
1010
apiUrl: string;
1111
children: React.ReactNode;
1212
options?: GenericObject;
13-
queryClient?: QueryClient;
1413
enableDevTools?: boolean;
1514
};
1615

1716
function StacApiProviderInner({
1817
children,
1918
apiUrl,
2019
options,
21-
}: Omit<StacApiProviderType, 'queryClient'>) {
20+
}: Omit<StacApiProviderType, 'enableDevTools'>) {
2221
const { stacApi } = useStacApi(apiUrl, options);
2322
const [collections, setCollections] = useState<CollectionsResponse>();
2423
const [items, setItems] = useState(new Map<string, Item>());
@@ -60,19 +59,30 @@ export function StacApiProvider({
6059
children,
6160
apiUrl,
6261
options,
63-
queryClient,
6462
enableDevTools,
6563
}: StacApiProviderType) {
64+
const existingClient = useContext(QueryClientContext);
6665
const defaultClient = useMemo(() => new QueryClient(), []);
67-
const client: QueryClient = queryClient ?? defaultClient;
6866

69-
if (enableDevTools && typeof window !== 'undefined') {
70-
// Connect TanStack Query DevTools (browser extension)
71-
window.__TANSTACK_QUERY_CLIENT__ = client;
67+
const client = existingClient ?? defaultClient;
68+
69+
// Setup DevTools once when component mounts or enableDevTools changes
70+
useMemo(() => {
71+
if (enableDevTools && typeof window !== 'undefined') {
72+
window.__TANSTACK_QUERY_CLIENT__ = client;
73+
}
74+
}, [client, enableDevTools]);
75+
76+
if (existingClient) {
77+
return (
78+
<StacApiProviderInner apiUrl={apiUrl} options={options}>
79+
{children}
80+
</StacApiProviderInner>
81+
);
7282
}
7383

7484
return (
75-
<QueryClientProvider client={client}>
85+
<QueryClientProvider client={defaultClient}>
7686
<StacApiProviderInner apiUrl={apiUrl} options={options}>
7787
{children}
7888
</StacApiProviderInner>

0 commit comments

Comments
 (0)