useState
で誤魔化していたのだけど、使ってみたら案外便利かも?とおもってちょっと素振りしたindex.tsx
enum DATA_FETCH_ACTION {
FETCH_COMPLETE = 'FETCH_COMPLETE'
}
interface DataFetchState<T> {
loading: boolean
error: Maybe<Error>
data: Maybe<T>
}
interface DataFetchAction<T> {
type: DATA_FETCH_ACTION
payload: T
error?: boolean
}
const dataFetchReducer = <T>(
state: DataFetchState<T>,
action: DataFetchAction<T>
): DataFetchState<T> => {
switch (action.type) {
case DATA_FETCH_ACTION.FETCH_COMPLETE: {
return {
...state,
loading: false,
data: action.payload
}
}
}
return state
}
const useRequest = <T>(url: string) => {
const [state, dispatch] = useReducer<
React.Reducer<DataFetchState<T>, DataFetchAction<T>>
>(dataFetchReducer, {
loading: true,
error: null,
data: null
})
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(json => {
if (json.data) {
dispatch({
type: DATA_FETCH_ACTION.FETCH_COMPLETE,
payload: json.data as T
})
} else {
// TODO
}
})
}, [])
return state
}
index.tsx
export const useFoo = ({ id }: Params) {
const state = useRequest<FooResponse>(`/api/foo/${id}`)
return state
}