React 18 Suspense minimal example

In the current version of React (17.0.2 at the day of this article creation) Suspense is a component, that allows developers to lazy-load application parts. It accepts fallback property, with content to display, while the child component is lazy-loadin…


This content originally appeared on DEV Community and was authored by vaukalak

In the current version of React (17.0.2 at the day of this article creation) Suspense is a component, that allows developers to lazy-load application parts. It accepts fallback property, with content to display, while the child component is lazy-loading.

const SomePage = React.lazy(() => import("./modules/somepage"));

const App () => (
  <React.Suspense fallback={"Loading..."}>
    <SomePage />
  </React.Suspense>
);

However from React 18 it will be possible to use Suspense for data fetching. This means, that fallback will be displayed until component will fetch all the data needed. Or in general all events that component expect will occur. Let say we want to just display placeholder for 2 seconds:

const Main = () => {
  useTimeout(2000);
  return <div>Component loaded</div>;
};

const App = () => (
  <Suspense fallback={"Loading..."}>
    <Main />
  </Suspense>
);

export default App;

As you could guess, Loading... will be displayed for 2 seconds and Component loaded afterwards.
However when I first saw the code above, I didn't understand HOW did that happen.. What is that magic mechanism in the useTimeout hook? In short it has to:

  1. Stop component code execution.
  2. Let Suspense know that the component isn't yet ready
  3. Notify Suspence know when it should re-attempt with rendering component.

To stop code execution you need use throw statement. In order to make Suspense know it's expected, the value thrown need to be a Promise. Suspense will catch this promise and subscribe to it, to re-attempt rendering.
Please note: the code bellow is just for a demo purpose:

let fullfilled = false;
let promise = null;

const useTimeout = (ms: number) => {
  // check if timeout already occurred.
  if (!fullfilled) {
    // if promise doesn't exist create and throw it.
    throw promise ||= new Promise((res) => {
      setTimeout(() => {
        // on next attempt consider timeout completed.
        fullfilled = true;
        // resolve promise (will ask react to re-render).
        res();
      }, ms);
    });
  }
};

(Confused about ||= ? Check this doc)

It turns out that suspense uses quite simple mechanisms, but there's a hard part. You might ask why fullfilled and promise couldn't be stored in a ref, so the hook would be reusable:

const fullfilled = useRef(false);

It turns out, that while component is not loaded, hooks can't be really used. Component will be unmounted / mounted on every render attempt before the render will complete without throwing promises. Hence to figure out, if this component has actually started data loading process, we should rely on a globally available cache. (In our simplified case it's just fullfilled variable). Of course in a real-world example such simple approach wouldn't work (this hook works only one time).

This is why it's advised to use good libraries that supports suspense (like swr).

Full code of the example above.

👋


This content originally appeared on DEV Community and was authored by vaukalak


Print Share Comment Cite Upload Translate Updates
APA

vaukalak | Sciencx (2022-01-22T19:07:22+00:00) React 18 Suspense minimal example. Retrieved from https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/

MLA
" » React 18 Suspense minimal example." vaukalak | Sciencx - Saturday January 22, 2022, https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/
HARVARD
vaukalak | Sciencx Saturday January 22, 2022 » React 18 Suspense minimal example., viewed ,<https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/>
VANCOUVER
vaukalak | Sciencx - » React 18 Suspense minimal example. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/
CHICAGO
" » React 18 Suspense minimal example." vaukalak | Sciencx - Accessed . https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/
IEEE
" » React 18 Suspense minimal example." vaukalak | Sciencx [Online]. Available: https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/. [Accessed: ]
rf:citation
» React 18 Suspense minimal example | vaukalak | Sciencx | https://www.scien.cx/2022/01/22/react-18-suspense-minimal-example/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.