Skip to content

Instantly share code, notes, and snippets.

@mjackson
Last active January 21, 2024 00:02
Show Gist options
  • Save mjackson/05c7749430d0ec87b66612733805bad6 to your computer and use it in GitHub Desktop.
Save mjackson/05c7749430d0ec87b66612733805bad6 to your computer and use it in GitHub Desktop.
import { useState, useEffect, useCallback } from 'react'
function usePromise(createPromise) {
const [error, setError] = useState()
const [value, setValue] = useState()
useEffect(() => {
let current = true
createPromise().then(
value => {
if (current) setValue(value)
},
error => {
if (current) setError(error)
}
)
return () => {
current = false
}
}, [createPromise])
return [error, value]
}
// Use it like this:
function Profile({ uid }) {
const [error, user] = usePromise(useCallback(() => fetchUser(uid), [uid]))
// ...
}
@erikras
Copy link

erikras commented May 22, 2019

That's sexy.

@naholyr
Copy link

naholyr commented May 22, 2019

Nice, is there a case where you'd not call useCallback around createPromise? Maybe you could do it for user? something like this:

function usePromise(createPromise, args = [], deps = args) {
  const createPromiseRef = useCallback(() => createPromise(...args), deps)

  ...
}

const [error, user] = usePromise(fetchUser, [uid])

@mjackson
Copy link
Author

There's a great linter for useCallback that warns you when you don't have the right deps. If I add deps to usePromise, I'd have to ship a linter rule with it as well or risk people not using the right dependencies. Making people call useCallback explicitly avoids that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment