in packages/runtime/src/Suspense.tsx [50:121]
export function useSuspenseData(request?: Request) {
const appContext = useAppContext();
const { requestContext } = appContext;
const suspenseState = React.useContext(SuspenseContext);
const { data, done, promise, update, error, id } = suspenseState;
const { hasHydrateData, data: hydrateData } = getHydrateData(id);
let thenable: Promise<any> = null;
if (!hasHydrateData && !error && !done && !promise && request) {
thenable = request(requestContext);
thenable.then((response) => {
update({
done: true,
data: response,
promise: null,
});
}).catch(e => {
update({
done: true,
error: e,
promise: null,
});
});
}
React.useEffect(() => {
// Update state in useEffect, otherwise it will cause bad setState warning.
if (thenable) {
update({
promise: thenable,
});
}
}, [thenable, update]);
// 1. Use data from server side directly when hydrate.
if (hasHydrateData) {
return hydrateData;
}
// 2. Check data request error, if error throw it to react.
if (error) {
throw error;
}
// 3. If request is done, return data.
if (done) {
if (process.env.NODE_ENV === 'development' && typeof data === 'object') {
return proxyData(data);
}
return data;
}
// 4. If request is pending, throw the promise to react.
if (promise) {
throw promise;
}
// 5. If no request, return null.
if (!request) {
return null;
}
if (!isClient) {
// 6. Create a promise for the request and throw it to react.
update({
promise: thenable,
});
}
throw thenable;
}