1

I'm playing with React suspense example. Everything makes sense to me except I don't know how to hide a promise from executing.

export function fetchProfileData() {
  let userPromise = fetchUser();
  return {
    user: wrapPromise(userPromise),
  };
}


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

In their example, whenever fetchProfileData in invoked, the promise is launched, and since the status is pending initially, it raises to the suspense for the loader.

But now where do I put the root ProfileDetails.

import { fetchProfileData } from "./fakeApi";

const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense
      fallback={<h1>Loading profile...</h1>}
    >
      <ProfileDetails />
    </Suspense>
  );
}

Suppose i have an app, do I just do

function App() {
  return <ProfilePage />
}

My question is, when is the promise executed in React? Right after I launch the page? If that's the case, how do I prevent it to be executed ex. if I'm not allowed to see that page. Do i do the following?

function App() {
  if (notAllowed) return
  return <ProfilePage />
}

Does this ever gonna work? I have serious doubt. Please help.

In the documentation it has this line, but i don't know what it means.

As a data fetching library author, you can enforce this by making it impossible to get a resource object without also starting a fetch. Every demo on this page using our “fake API” enforces this.

windmaomao
  • 7,120
  • 2
  • 32
  • 36
  • Where are you using the `resource` variable in your code? Or is that the question? – Bergi Jul 27 '21 at 21:21
  • "*when is the promise executed*" - in your current code, the fetch request is made as soon as you call `fetchProfileData()`, which is when the module is loaded – Bergi Jul 27 '21 at 21:24
  • @Bergi, you are right! I am curious how to prevent it from invoking:) If for some reason i don't want to have the API under certain condition. – windmaomao Jul 28 '21 at 16:19
  • From my understanding, data-loading `Suspense` is currently not at all supported by React, and the [experiment from React 16 is outdated](https://reactjs.org/docs/concurrent-mode-suspense.html). However, if that's the code you were using, they have [an example of putting a "resource" (on which to suspend) in the component state](https://reactjs.org/docs/concurrent-mode-suspense.html#solving-race-conditions-with-suspense) – Bergi Jul 28 '21 at 16:42

1 Answers1

0

Ok, I found one answer from other libraries consumes this.

import { useAsyncResource } from 'use-async-resource';

const fetchUser = (id: number) => fetch(`.../get/user/by/${id}`).then(res => res.json());

function App() {
  const [userReader, getNewUser] = useAsyncResource(fetchUser, 1);

So the fetch is wrapped inside a function () => {...}, and send to a hook , and it's up to this hook when is the right time to invoke it.

Therefore to answer the question, we need to define a wrapper as a handler.

  const fetchResource = () => {
    return fetchProfileData
  }
    

and then

function App() {
  if (isNotAllowed) return
  
  return <ProfilePage resource={fetchResource()} />
}
windmaomao
  • 7,120
  • 2
  • 32
  • 36