You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It looks like there is an issue with the current suspense implementation.
Considering this snippet
const { data } = useAsync({
suspense: true,
promise: new Promise(resolve => {
setTimeout(() => resolve('hello'), 1000)
}),
})
// we should be able to safely use data here as this line
// should not be reached until promise has resolved
console.log('data', data)
But we get the following output
data undefined
data hello
One of the most important purpose of suspense is to make asynchronous code feel like if it were synchronous so you don't have to deal with "data is not here yet" headaches.
By quickly looking at the implementation, this may be due to this condition
if (options.suspense && state.isPending && lastPromise.current !== neverSettle) {
// Rely on Suspense to handle the loading state
throw lastPromise.current
}
If lastPromise.current equals neverSettle during the first render, then it won't throw and the first render will not be suspended.
Regards
The text was updated successfully, but these errors were encountered:
hrougier
changed the title
Suspense support
Suspense does not suspend on first render
Jan 12, 2020
This is the part why the current Suspense support is marked experimental. It works, but it's not optimized. If you can provide a PR that fixes this I'll happily merge it.
i think tests like these describe the behavior accurately
im looking into this but can't guarantee anything
// Skip when testing for backwards-compatibility with React 16.3consttestSuspense=Suspense ? test : testtestSuspense("supports Suspense",async()=>{constpromiseFn=()=>resolveIn(150)("done")constlog=[]render(<Suspensefallback={<div>fallback</div>}><AsyncsuspensepromiseFn={promiseFn}>{({ data, isPending, isResolved, status })=>{expect(status).toBe("resolved")expect(data).toBe("done")expect(isResolved).toBe(true)expect(isPending).toBe(false)returnnull}}</Async></Suspense>)})testSuspense("supports Error Boundaries",async()=>{constpromiseFn=()=>rejectIn(150)(newError("error"))constlog=[]render(<ErrorBoundaryfallback={<div>fallback</div>}><AsyncsuspensepromiseFn={promiseFn}>{({ error, isPending, isRejected, status })=>{expect(status).toBe("rejected")expect(error).toBe("error")expect(isRejected).toBe(true)expect(isPending).toBe(false)returnnull}}</Async></ErrorBoundary>)})
Hi,
It looks like there is an issue with the current suspense implementation.
Considering this snippet
But we get the following output
One of the most important purpose of suspense is to make asynchronous code feel like if it were synchronous so you don't have to deal with "data is not here yet" headaches.
By quickly looking at the implementation, this may be due to this condition
If
lastPromise.current
equalsneverSettle
during the first render, then it won't throw and the first render will not be suspended.Regards
The text was updated successfully, but these errors were encountered: