/**
 * Since solution using Suspense API we should be looking at Render-as-you-fetch pattern.
 * Start fetching all the required data for the next screen as early as possible, and start rendering the new screen immediately.
 *
 * The 3-state pattern is very common for loading any resources.
 * It is in fact so common that it has a name.
 * Any object containing a read function that behaves like this 3-state pattern, is called a resource.
 *
 * Issues
 * 1) Suspense tag missing attribute 'fallback' prop
 * 2) Data is not being fetched early
 * 3) Fetching data on useEffect might cause Race condition. using UseEffect is like Fetch-Then-Render pattern we should avoid.
 *
 * Optional but Useful: Handling Errors
 * Since we are using Promises, we might use catch() to handle errors.
 * Use ErrorBoundary class and then we can put it anywhere in the tree to catch errors
 */
import React, { Suspense } from "react";
// Error boundaries currently have to be classes.
class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };
  static getDerivedStateFromError(error) {
    return {
      hasError: true,
      error
    };
  }
  render() {
    if (this.state.hasError) {
      return this.props.fallback;
    }
    return this.props.children;
  }
}
function fetchProfileData(userId) {
  let userPromise = fetchUserProfilePromise(userId);
  return wrapPromise(userPromise);
}
// Suspense integrations like Relay implement
// a contract like this to integrate with React.
// Real implementations can be significantly more complex.
// Don't copy-paste this into your project!
function wrapPromise(promise) {
  let status = "pending";
  let result;
  let suspender = promise.then(
    (r) => {
      status = "success";
      result = r;
    },
    (e) => {
      status = "error";
      result = e;
    }
  );
  return {
    read() {
      if (status === "pending") {
        throw suspender;
      } else if (status === "error") {
        throw result;
      } else if (status === "success") {
        return result;
      }
    }
  };
}
const fetchUserProfilePromise = (userId) =>
  fetch(`https://jsonplaceholder.typicode.com/users/${userId}`).then((res) =>
    res.json()
  );
const SuspensefulUserProfile = ({ resource }) => {
  const data = resource.read();
  return