Skip to content

Instantly share code, notes, and snippets.

@tannerlinsley
Created January 25, 2019 17:00
Show Gist options
  • Save tannerlinsley/dcd6181c1d5c836e1b2c8dfe65cc9c8c to your computer and use it in GitHub Desktop.
Save tannerlinsley/dcd6181c1d5c836e1b2c8dfe65cc9c8c to your computer and use it in GitHub Desktop.
useCancellable, useRefresh combo
const useCancellable = fn => {
const requestRef = useRef(0)
return async (...args) => {
// Keep track of latest promise ID
const id = Date.now()
requestRef.current = id
// Wait for resolution
const res = await fn(...args)
if (requestRef.current !== id) {
// If a new request has happened...
throw new Error(useCancellable)
}
// All is well
return res
}
}
const useRefresh = (fn, time) => {
if (!time) {
throw new Error('useRefresh requires a time')
}
// Keep track of the last time requested
const lastRequestedRef = useRef(Date.now())
// Any time we refresh...
const refresh = () => {
// Update the last requested
lastRequestedRef.current = Date.now()
// return the func
return fn()
}
// If and when the lastRequested changes, set
// a timeout to refresh after the time
useEffect(
() => {
const timeoutID = setTimeout(refresh, time)
return () => {
// If the lastRequested changes before the
// timeout, clear it and start over
clearTimeout(timeoutID)
}
},
[lastRequestedRef.current]
)
// Supply the refresher
return refresh
}
function useSearches(guards = []) {
// Some crud state
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const [searches, setSearches] = useState([])
// A cancellable promise will throw `useCancellable`
const getSearches = useCancellable(() => axios.get(`${endpoint}/searches`))
// Build the refresher
const refresh = useRefresh(async () => {
setError(null)
setLoading(true)
try {
const { data } = await getSearches()
setSearches(data)
} catch (err) {
if (err === useCancellable) {
// Was cancelled
}
setError(err)
} finally {
setLoading(false)
}
}, 1000 * 60)
// When the guards change, refresh
useEffect(() => {
refresh()
}, guards)
return { searches, loading, error, refresh }
}
// Photo by Maksym Zakharyak on Unsplash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment