Skip to content

Instantly share code, notes, and snippets.

@enpitsuLin
Created February 20, 2024 06:25
Show Gist options
  • Save enpitsuLin/a404d258f52a5ad1abdfbacf4f0963a9 to your computer and use it in GitHub Desktop.
Save enpitsuLin/a404d258f52a5ad1abdfbacf4f0963a9 to your computer and use it in GitHub Desktop.
get an async value with useSyncExternalStore
import { useCallback, useRef, useState, useSyncExternalStore } from 'react'
type Listener = () => void
interface UseAsyncReturn<T> {
data: T | undefined
error: any
isLoading: boolean
refresh: () => void
}
const __listeners = new Set<Listener>()
function subscribe(listener: Listener) {
__listeners.add(listener)
return () => __listeners.delete(listener)
}
export function useAsync<T>(getAsync: () => Promise<T>): UseAsyncReturn<T> {
const cache = useRef<T>()
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState()
const currentCache = useSyncExternalStore<T | undefined>(
subscribe,
() => cache.current,
)
const refresh = useCallback(() => {
setIsLoading(true)
getAsync()
.then((m) => {
cache.current = m
setIsLoading(false)
})
.catch((error) => {
setIsLoading(false)
setError(error)
})
}, [getAsync])
return {
data: currentCache,
isLoading,
error,
refresh,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment