We're planting a tree for every job application! Click here to learn more

Suspense on React: The Act of Rendering While You Load

King Somto

21 Oct 2021

•

3 min read

Suspense on React: The Act of Rendering While You Load
  • JavaScript

Intro

React in version 16.6 added the Suspense component that lets developers load components asynchronously, this happens by preventing the component from rendering while it fetches data all while providing an option to show a loading UI or fallback of choice to be displayed while fetching data, this helps create a smother state or transition.

Let's look at why we need a suspense operation

import React from "react";
import "./styles.css";
 
export default function App() {
 const [show, setShow] = React.useState(false);
 
 const loadApp = async () => {
   const promise = new Promise((resolve, reject) => {
     setTimeout(() => {
       setShow(true);
       resolve();
     }, 4000);
   });
 
   await promise;
 };
 
 React.useEffect(() => {
   loadApp();
 }, []);
 
 return (
   <div className="App">
     {show && (
       <div>
         <h1>Hello</h1>
         <h2>Tutorial on React Suspense!</h2>
       </div>
     )}
   </div>
 );
}

The code above waits for an asynchronous operation to be completed before rendering the content on the page which isn't really a good idea, currently, we have a set fixed time for our async function, but what about if we were making an API call and the internet is slow, we need to let the user know that data is being loaded.

Now let's edit the code above to let us give the app a wait state,

import React from "react";
import "./styles.css";
 
export default function App() {
 const [show, setShow] = React.useState(false);
 
 const loadApp = async () => {
   const promise = new Promise((resolve, reject) => {
     setTimeout(() => {
       setShow(true);
       resolve();
     }, 4000);
   });
 
   await promise;
 };
 
 React.useEffect(() => {
   loadApp();
 }, []);
 
 if (!show) {
   return <h2>Loading.........</h2>;
 }
 
 return (
   <div className="App">
     {show && (
       <div>
         <h1>Hello</h1>
         <h2>Tutorial on React Suspense!</h2>
       </div>
     )}
   </div>
 );
}

The above codebase has a loading state or a default UI rendered by the app while it waits for the promise to be fulfilled, this transition lets users know that an operation is taking place in the application.

Applying Suspense

To take advantage of React.suspense we have to wrap our promise first let's implement that below

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

The function above takes in the promise and returns a read function that can be called by react to check if the operation is done.

Let's look at a full example.

import React, { Suspense } from "react";
 
const loadApp = async () => {
 const promise = new Promise((resolve, reject) => {
   setTimeout(() => {
     resolve({
       state: "done"
     });
   }, 4000);
 });
 
 await promise;
};
 
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 suspenderCheck = wrapPromise(loadApp());
 
const ChildComponent = () =>{
 const data = suspenderCheck.read()
 return <div>
 <h1>Hello</h1>
 <h2>Tutorial on React Suspense!</h2>
</div>
}
 
export default function App() {
 return (
   <div className="App">
     <Suspense fallback={<h2>{"Loading with suspense......."}</h2>}>
        <ChildComponent/>
     </Suspense>
   </div>
 );
}

Breaking the code down

export default function App() {
 return (
   <div className="App">
     <Suspense fallback={<h2>{"Loading with suspense......."}</h2>}>
        <ChildComponent/>
     </Suspense>
   </div>
 );
}

We first call our Suspense Component to wrap our child component also passing a fallback parameter in our component. The fallback parameter is the component that would be rendered until the ChildComponent is done loading.

const suspenderCheck = wrapPromise(loadApp());
 
const ChildComponent = () =>{
 const data = suspenderCheck.read()
 return <div>
 <h1>Hello</h1>
 <h2>Tutorial on React Suspense!</h2>
</div>
}

Here we wrap our promise and call the read function inside the ChildComponent this triggers the Suspense operation to wait for the wrapped promise to be resolved.

Lazy Loading

React has a big problem with application size, apps are getting heavier and users now have to pay a bigger price to download the code, for users with older devices or network issues this could be a problem.

A cool approach would be to tell react not to load some components immediately this can be done with React.lazy.

Doing this alone causes a problem since some components are not being loaded at the same time with others, there would be a lot of empty spaces, we need to let users know that an operation is being performed, that's where React.Suspense comes in here is an example.

import React from 'react';
const Component = React.lazy(() => import('./path/to/component));
// Displays " Component loading..." to the user until Component loads
// is done loading.
export const App = () => (
 <React.Suspense fallback="Component loading...">
   <Component />
 </React.Suspense>
);

Conclusion React.suspense is an amazing tool used by developers to be able to show a loader while components are not available to be rendered, this can be because data is not available or the component is actually being loaded later on, this article was simplified to explain the basic concepts of React.suspense for more info please check the React page.

Did you like this article?

King Somto

Dev

See other articles by King

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub