export function useSuspenseData()

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;
}