We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies.

We use cookies and other tracking technologies to improve your browsing experience on our site, analyze site traffic, and understand where our audience is coming from. To find out more, please read our privacy policy.

By choosing 'I Accept', you consent to our use of cookies and other tracking technologies. Less

We use cookies and other tracking technologies... More

Login or register
to publish this job!

Login or register
to save this job!

Login or register
to save interesting jobs!

Login or register
to get access to all your job applications!

Login or register to start contributing with an article!

Login or register
to see more jobs from this company!

Login or register
to boost this post!

Show some love to the author of this blog by giving their post some rocket fuel 🚀.

Login or register to search for your ideal job!

Login or register to start working on this issue!

Login or register
to save articles!

Login to see the application

Engineers who find a new job through JavaScript Works average a 15% increase in salary 🚀

You will be redirected back to this page right after signin

Blog hero image

Suspense on React: The Act of Rendering While You Load

King Somto 21 October, 2021 | 3 min read

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.

Author's avatar
King Somto
I really dont know much but am willing to try and learn

Related Issues

open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 2
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 2
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Open
  • 0
  • 0
  • Intermediate
  • HTML
open-editions / corpus-joyce-ulysses-tei
open-editions / corpus-joyce-ulysses-tei
  • Started
  • 0
  • 1
  • Intermediate
  • HTML

Get hired!

Sign up now and apply for roles at companies that interest you.

Engineers who find a new job through JavaScript Works average a 15% increase in salary.

Start with GitHubStart with Stack OverflowStart with Email