So i have a custom hook that may or may not call the API
import { useState, useEffect } from 'react'
import { get } from 'resources/client'
const useAuth = () => {
const [user, setUser] = useState(null)
useEffect(() => {
const lsUserStr = global.localStorage.getItem('auth-user')
if (lsUserStr) {
const lsUser = JSON.parse(lsUserStr)
setUser(lsUser)
} else {
refreshUser()
}
}, [])
const refreshUser = async () => {
const user = await get('auth/me')
localStorage.setItem('auth-user', JSON.stringify(user))
setUser(user)
return user
}
return [user, refreshUser]
}
export default useAuth
now, in my main component, i would like to use Suspense, to account on wait
const Component = () => {
const [user, refreshUser] = useAuth()
console.log({ user })
return (
<Layout>
<h1>Dashboard</h1>
<h3>
Welcome, {user.name}
</h3>
</Layout>
)
}
Edit
Because it's a React Hook that uses useEffect and useState, i can't return a promise from here so that suspense would wait so, in the component, user will always be initialized as null and will only get a value after first render.
I have tried returning a promise from the hook, and it still doesn't work:
const useAuth = () => {
const [theUser, setUser] = useState(new Promise(() => {}))
useEffect(() => {
const lsUserStr = localStorage.getItem('auth-user')
if (lsUserStr) {
const lsUser = JSON.parse(lsUserStr)
setTimeout(() => setUser(lsUser), 2000)
// setUser(lsUser)
}
}, [])
return [user]
}
const Dashboard = () => {
const [user] = useAuth()
console.log(user)
return (
<Layout>
<Suspense fallback={<div>loading</div>}>
<h1>Dashboard</h1>
<h3>
Welcome, {user.first_name} {user.last_name}
</h3>
</Suspense>
</Layout>
)
}
now it doesn't break because user is initially a Promise (object) but it doesn't fallback, it just shows me 'Welcome, ' for two seconds and then fills the data
end Edit
If i try to wrap my component with a Suspense tag, Suspense doesn't know what it's waiting for.
How do other libraries manage to do this?