React:Suspense for data fetching (part 2)

React:Suspense for data fetching (part 2) - Aug 13

Hello 👋,

In the first part, we explained React Suspense APi, what it does and how it works in conjunction with lazy components.

In this last part, we will see how to use React Suspense when it comes to fetching data. When the process still loading in the background, React Suspense displays a fallback to let the user know that there is some process going behind the scene.

To follow along if you didn't read the first part of this series click here to read it.
A basic understanding of JSON server, you can read it here

all the code in this article can be found on GitHub here.

First, you need to clone the repo in your local machine,
next, Open the repo in your text editor, in my case I'm using VScode,
we have two folders: web-client and server.
Open up your terminal: Control + J for windows users and Command + J for mac users.
you should be in this directory:

Folder Structure
add a second terminal
Two terminals
To install all the dependencies, in the first terminal navigate to web-client directory then run npm install, and do the same in the server directory but in the second terminal.

When all the dependencies are installed, inside the server directoryrun the command npm run serve-json, aport 7000 will be running on your machine and npm run dev inside web-client. go to localhost:3000 your browser to access the website.

Running the servers
Now let's fetch data from the fake REST API which is running on our localhost:7000/data.

to do that let's create a new file inside web-client/src/page/FiciGame/
name it fetchFici.js

Inside past the code below:

const fetchFici = (search) => {
    return fetch(`http://localhost:7000/data?q=${search}`)
        .then(res => res.json())
        .catch(err => console.log(err))

const 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;
            return result;

export const createResource = (search) => {
    return {
        data: wrapPromise(fetchFici(search))

Enter fullscreen mode Exit fullscreen mode


the first function fetchFici fetches data according to the parameter passed in.

to have this work we are going to create a function that going to take a promise as a parameter, inside we create a string variable called status with 'pending' as a default value. this will keep track of whether a promise is completed or whether is loading or complete.
the next line is a variable that going to wait for the promise.

at the bottom, we return a function that is going to read and check the status.
React Suspense expects us to throw a promise so it can catch it.

Last we export a function that returns an object, inside that object we passe fetchFici() which is going to return a promise that we are wrapping inside wrapPromise making sure it fits the Suspense API.

Once we have this setup we can reuse it.

import React, { Suspense, useState } from 'react'
import Spinner from '../../layout/spinner';
import { createResource } from './fetchFici';
const FiciGame = () => {
    const [fici, setFici] = useState('Fire')
    const resource = createResource(fici);

    return (
        <div className='border rounded-md bg-zinc-800 border-white p-4'>
            <p className='text-center text-3xl font-mono'>Fici Game</p>
            <Suspense fallback={<Spinner />}>
             //Component to be add
            <ul className='flex justify-center gap-2 items-center'>
                <li onClick={() => setFici('Fire')} className='p-4 border hover:cursor-pointer text-2xl shadow-lg  bg-gray-900 border-white'>Fire</li>
                <li onClick={() => setFici('Rock')} className='p-4 border hover:cursor-pointer text-2xl shadow-lg  bg-gray-900 border-white'>Rock</li>
                <li onClick={() => setFici('Water')} className='p-4 border hover:cursor-pointer text-2xl shadow-lg  bg-gray-900 border-white'>Water</li>
                <li onClick={() => setFici('Air')} className='p-4 border hover:cursor-pointer text-2xl shadow-lg  bg-gray-900 border-white'>Air</li>

export default FiciGame
Enter fullscreen mode Exit fullscreen mode


Inside index.jsx we create a useState that takes a string value.
We then set the value according to the <li> tag that will be pressed.

then we import creacteRessource() which we save in resource, inside we pass the string got from fici.

Next, we import suspense component from react, we pass a fallback function which will be displayed while the data are fetching in the background.
Inside the suspense api we are going to create a component (i called it Screen) that will render after the process is done.

Now let's create that component.
Inside web-client/src/page/FiciGame/ create a file called screen.jsx, inside that file type this code:

import React from 'react'

const Screen = (props) => {
    const { resource } = props;
    const ficiData =
    const ficiName = ficiData[0].name
    const ficiSymbol = ficiData[0].symbol

    return (
        <div className='border bg-gray-900 flex flex-col space-y-4 justify-center items-center border-white h-80 m-4'>
            <p className="p-4 font-mono text-lg">{ficiName}</p>
            <span className='text-9xl shadow-2xl rounded-full'>{ficiSymbol}</span>

export default Screen
Enter fullscreen mode Exit fullscreen mode

We are calling; if it still loading, it will throw a promise which is going to be caught by suspense component and it's going to display a loading indicator otherwise we got our data and display it.

Go back to index.jsx and import Screen.jsx and place it inside Suspense component then save all your files.

import Screen from './screen';

const FiciGame = () => {
    return (
            <Suspense fallback={<Spinner />}>
                <Screen resource={resource} />

export default FiciGame
Enter fullscreen mode Exit fullscreen mode


To test this, go to your browser open up your devtool in the network tab, look on the top No throttling choose fast 3G then refresh the page.

Congratulation you're now a master of using the Suspense APi and lazy loading component, don't hesitate to try it out. It seems slightly more complex but with more practice, you will get the hang of it.

Don't forget to leave a comment or chat with me on Twitter.

See you 👋