Deepeshmhatre
Deepeshmhatre

Reputation: 11

React 18 Suspense Fallback not working on Data Fetching?

I am basically fetching a bunch of user data and displaying a list of their usernames on page load. I am using the suspense with the intention of displaying the "Loading..." text while the userList component is being processed, but for some reason it does'nt display the loading text mentioned inside the fallback. I am using the latest react 18 version.

import React, { useState, useEffect, Suspense } from "react";

function UsersList() {
  // Fetches and returns List of users
  const [users, setUsers] = useState([]);
  useEffect(() => {
    try {
      fetch("https://jsonplaceholder.typicode.com/users")
        .then((response) => response.json())
        .then((data) => setUsers(data));
    } catch (error) {
      // handle the error here
    }
  }, []);

  return (
    <div>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

function App() {
  return (
    <div className="App">
      <h2>Users List</h2>
      <Suspense fallback={<h1> Loading...</h1>}>
        <h4> Below are the user detailed fetched : </h4>
        <UsersList />
      </Suspense>
    </div>
  );
}

export default App;

I tried using throttling to reduce network speed on chrome dev tool, but still the loading text is not being displayed.

Upvotes: 1

Views: 1968

Answers (2)

LiangYen
LiangYen

Reputation: 23

You can change the code as below:

   import React,{useMemo,useState,Suspense} from 'react';

   const wrapResponse = (promise) => {
        let status = 'pending';
        let data = '';
        let error = '';
        promise
        .then(r => r.json())
        .then(r => {
            status = 'success';
            data = r;
        }).catch(e => {
            status = 'error';
            error = e;
        })
        return {
            read(){
                  if(status === 'pending')
                     throw promise;
                  else if(status === 'success')
                     return data;
                  else if(status === 'error')
                     throw error;
            }
        }
    }
    function UsersList({resource}) {
     // Fetches and returns List of users
     // If fetch is pending , throw the promise and React will try to first 
     // render UserList again with fallback UI: Loading...
     const result = resource?.read();
     const [users, setUsers] = useState(result);

     return (
       <div>
         <ul>
           {users.map((user) => (
             <li key={user.id}>{user.name}</li>
           ))}
         </ul>
       </div>
     );
    
    function App() {
       const resource = useMemo(() => 
            wrapResponse(fetch("https://jsonplaceholder.typicode.com/users")),[]);
       return (
        <div className="App">
          <h2>Users List</h2>
          <Suspense fallback={<h1> Loading...</h1>}>
            <h4> Below are the user detailed fetched : </h4>
            <UsersList resource={resource}/>
          </Suspense>
        </div>
       );
    }
  }

Just wrap the Component which might throw Promise with Suspense Component , and if data is ready , status will change from 'pending' to 'success', UI will change from 'Loading...' to your ready UserList Component.

Upvotes: 2

Mr Patience
Mr Patience

Reputation: 2200

How does Suspense is suppose to know that you're in the process of fetching the data?

From the docs:

Only Suspense-enabled data sources will activate the Suspense component.
They include:

  • Data fetching with Suspense-enabled frameworks like Relay and Next.js
  • Lazy-loading component code with lazy

Suspense does not detect when data is fetched inside an Effect or event handler.

Suspense-enabled data fetching without the use of an opinionated framework is not yet supported. The requirements for implementing a Suspense-enabled data source are unstable and undocumented. An official API for integrating data sources with Suspense will be released in a future version of React.

Tl;DR: You can't easily use it by yourself yet.

Upvotes: 1

Related Questions