https://www.smashingmagazine.com/2020/07/custom-react-hook-fetch-cache-data/
| import { useEffect, useRef, useReducer } from 'react'; | |
| export const useFetch = (url) => { | |
| 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); | |
| useEffect(() => { | |
| let cancelRequest = false; | |
| if (!url) return; | |
| const fetchData = async () => { | |
| dispatch({ type: 'FETCHING' }); | |
| if (cache.current[url]) { | |
| const data = cache.current[url]; | |
| dispatch({ type: 'FETCHED', payload: data }); | |
| } else { | |
| try { | |
| const response = await fetch(url); | |
| const data = await response.json(); | |
| cache.current[url] = data; | |
| if (cancelRequest) return; | |
| dispatch({ type: 'FETCHED', payload: data }); | |
| } catch (error) { | |
| if (cancelRequest) return; | |
| dispatch({ type: 'FETCH_ERROR', payload: error.message }); | |
| } | |
| } | |
| }; | |
| fetchData(); | |
| return function cleanup() { | |
| cancelRequest = true; | |
| }; | |
| }, [url]); | |
| return state; | |
| }; |
Comments
Post a Comment