1- import { useState , useEffect , useCallback } from 'react' ;
1+ import { useEffect , useState } from 'react' ;
2+ import { useQuery } from '@tanstack/react-query' ;
23import { Item } from '../types/stac' ;
34import { ApiError , LoadingState } from '../types' ;
45import { useStacApiContext } from '../context/useStacApiContext' ;
@@ -11,71 +12,55 @@ type ItemHook = {
1112} ;
1213
1314function useItem ( url : string ) : ItemHook {
14- const { stacApi, getItem , addItem , deleteItem } = useStacApiContext ( ) ;
15+ const { stacApi } = useStacApiContext ( ) ;
1516 const [ state , setState ] = useState < LoadingState > ( 'IDLE' ) ;
16- const [ item , setItem ] = useState < Item > ( ) ;
17- const [ error , setError ] = useState < ApiError > ( ) ;
1817
19- useEffect ( ( ) => {
20- if ( ! stacApi ) return ;
21-
22- setState ( 'LOADING' ) ;
23- new Promise ( ( resolve , reject ) => {
24- const i = getItem ( url ) ;
25- if ( i ) {
26- resolve ( i ) ;
27- } else {
28- stacApi
29- . fetch ( url )
30- . then ( ( r : Response ) => r . json ( ) )
31- . then ( ( r : Item ) => {
32- addItem ( url , r ) ;
33- resolve ( r ) ;
34- } )
35- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
36- . catch ( ( err : unknown ) => reject ( err ) ) ;
18+ const fetchItem = async ( ) : Promise < Item > => {
19+ if ( ! stacApi ) throw new Error ( 'No STAC API configured' ) ;
20+ const response : Response = await stacApi . get ( url ) ;
21+ if ( ! response . ok ) {
22+ let detail ;
23+ try {
24+ detail = await response . json ( ) ;
25+ } catch {
26+ detail = await response . text ( ) ;
3727 }
38- } )
39- . then ( setItem )
40- . catch ( ( err : unknown ) => setError ( err as ApiError ) )
41- . finally ( ( ) => setState ( 'IDLE' ) ) ;
42- } , [ stacApi , addItem , getItem , url ] ) ;
43-
44- const fetchItem = useCallback ( ( ) => {
45- if ( ! stacApi ) return ;
28+ const err = Object . assign ( new Error ( response . statusText ) , {
29+ status : response . status ,
30+ statusText : response . statusText ,
31+ detail,
32+ } ) ;
33+ throw err ;
34+ }
35+ return await response . json ( ) ;
36+ } ;
4637
47- setState ( 'LOADING' ) ;
48- new Promise ( ( resolve , reject ) => {
49- const i = getItem ( url ) ;
50- if ( i ) {
51- resolve ( i ) ;
52- } else {
53- stacApi
54- . fetch ( url )
55- . then ( ( r : Response ) => r . json ( ) )
56- . then ( ( r : Item ) => {
57- addItem ( url , r ) ;
58- resolve ( r ) ;
59- } )
60- // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
61- . catch ( ( err : unknown ) => reject ( err ) ) ;
62- }
63- } )
64- . then ( setItem )
65- . catch ( ( err : unknown ) => setError ( err as ApiError ) )
66- . finally ( ( ) => setState ( 'IDLE' ) ) ;
67- } , [ addItem , getItem , stacApi , url ] ) ;
38+ const {
39+ data : item ,
40+ error,
41+ isLoading,
42+ isFetching,
43+ refetch,
44+ } = useQuery < Item , ApiError > ( {
45+ queryKey : [ 'item' , url ] ,
46+ queryFn : fetchItem ,
47+ enabled : ! ! stacApi ,
48+ retry : false ,
49+ } ) ;
6850
69- const reload = useCallback ( ( ) => {
70- deleteItem ( url ) ;
71- fetchItem ( ) ;
72- } , [ deleteItem , fetchItem , url ] ) ;
51+ useEffect ( ( ) => {
52+ if ( isLoading || isFetching ) {
53+ setState ( 'LOADING' ) ;
54+ } else {
55+ setState ( 'IDLE' ) ;
56+ }
57+ } , [ isLoading , isFetching ] ) ;
7358
7459 return {
7560 item,
7661 state,
77- error,
78- reload,
62+ error : error as ApiError ,
63+ reload : refetch ,
7964 } ;
8065}
8166
0 commit comments