Skip to content

Commit e57e3a0

Browse files
committed
feat: Add error handling for useItem
1 parent 0c6cfdb commit e57e3a0

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed

src/hooks/useItem.test.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ describe('useItem', () => {
1010

1111
it('queries item', async () => {
1212
fetch
13-
.mockResponseOnce(JSON.stringify({ id: 'abc' }))
1413
.mockResponseOnce(JSON.stringify({ id: 'abc', links: [] }))
1514
.mockResponseOnce(JSON.stringify({ id: 'abc' }));
1615

@@ -22,4 +21,40 @@ describe('useItem', () => {
2221
expect(result.current.item).toEqual({ id: 'abc' });
2322
expect(result.current.state).toEqual('IDLE');
2423
});
24+
25+
it('handles error with JSON response', async () => {
26+
fetch
27+
.mockResponseOnce(JSON.stringify({ id: 'abc', links: [] }))
28+
.mockResponseOnce(JSON.stringify({ error: 'Wrong query' }), { status: 400, statusText: 'Bad Request' });
29+
30+
const { result, waitForNextUpdate } = renderHook(
31+
() => useItem('https://fake-stac-api.net/items/abc'),
32+
{ wrapper }
33+
);
34+
await waitForNextUpdate();
35+
36+
expect(result.current.error).toEqual({
37+
status: 400,
38+
statusText: 'Bad Request',
39+
detail: { error: 'Wrong query' }
40+
});
41+
});
42+
43+
it('handles error with non-JSON response', async () => {
44+
fetch
45+
.mockResponseOnce(JSON.stringify({ id: 'abc', links: [] }))
46+
.mockResponseOnce('Wrong query', { status: 400, statusText: 'Bad Request' });
47+
48+
const { result, waitForNextUpdate } = renderHook(
49+
() => useItem('https://fake-stac-api.net/items/abc'),
50+
{ wrapper }
51+
);
52+
await waitForNextUpdate();
53+
54+
expect(result.current.error).toEqual({
55+
status: 400,
56+
statusText: 'Bad Request',
57+
detail: 'Wrong query'
58+
});
59+
});
2560
});

src/hooks/useItem.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,47 @@
11
import { useState, useEffect} from 'react';
22
import { Item } from '../types/stac';
3-
import { LoadingState } from '../types';
3+
import { ApiError, LoadingState } from '../types';
44
import { useStacApiContext } from '../context';
55

66
type ItemHook = {
77
item?: Item
88
state: LoadingState
9+
error?: ApiError
910
}
1011

1112
function useItem(url: string): ItemHook {
12-
const { getItem, addItem } = useStacApiContext();
13+
const { stacApi, getItem, addItem } = useStacApiContext();
1314
const [ state, setState ] = useState<LoadingState>('IDLE');
1415
const [ item, setItem ] = useState<Item>();
16+
const [ error, setError ] = useState<ApiError>();
1517

1618
useEffect(() => {
19+
if (!stacApi) return;
20+
1721
setState('LOADING');
18-
new Promise((resolve) => {
22+
new Promise((resolve, reject) => {
1923
const i = getItem(url);
2024
if (i) {
2125
resolve(i);
2226
} else {
23-
fetch(url)
27+
stacApi.fetch(url)
2428
.then(r => r.json())
2529
.then(r => {
2630
addItem(url, r);
2731
resolve(r);
28-
});
32+
})
33+
.catch((err) => reject(err));
2934
}
3035
})
3136
.then(setItem)
37+
.catch((err) => setError(err))
3238
.finally(() => setState('IDLE'));
33-
}, [addItem, getItem, url]);
39+
}, [stacApi, addItem, getItem, url]);
3440

3541
return {
3642
item,
37-
state
43+
state,
44+
error
3845
};
3946
}
4047

0 commit comments

Comments
 (0)