Skip to content

Instantly share code, notes, and snippets.

@mamapi
Created March 9, 2021 12:30
Show Gist options
  • Select an option

  • Save mamapi/d4531e834a541af62c5dc1696afc4936 to your computer and use it in GitHub Desktop.

Select an option

Save mamapi/d4531e834a541af62c5dc1696afc4936 to your computer and use it in GitHub Desktop.
React hook to fetch data with cache
import React, { useRef, useReducer } from 'react'
import { fetchJson } from 'apis'
export function useFetchWithCache({
url,
options,
}) {
const cache = useRef({})
const initialState = {
status: 'idle',
error: null,
data: [],
}
const [state, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'FETCHING':
return { ...initialState, status: 'fetching' }
case 'FETCHED':
return { ...initialState, status: 'fetched', data: action.payload }
case 'FETCH_ERROR':
return { ...initialState, status: 'error', error: action.payload }
default:
return state
}
}, initialState)
React.useEffect(() => {
let cancelRequest = false
if (!url) return
dispatch({ type: 'FETCHING' })
if (cache.current[url]) {
const data = cache.current[url]
dispatch({ type: 'FETCHED', payload: data })
} else {
fetchJson(url, options)
.then(json => {
if (!cancelRequest) {
cache.current[url] = json
dispatch({ type: 'FETCHED', payload: json })
}
})
.catch(err => {
if (!cancelRequest) {
dispatch({ type: 'FETCH_ERROR', payload: err })
}
})
}
return function cleanup() {
cancelRequest = true
}
}, [url])
return [ state.data, state.error, state.status]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment