Reputation: 880
I am using <React.Suspense>
for data fetching like in this blog post.
From the react docs
Suspense lets your components wait for something before they can render.
And even better explained in this docs
React.Suspense
lets you specify the loading indicator in case some components in the tree below it are not yet ready to render
I have understood that a loading indicator specified as fallback prop in <React.Suspense>
is displayed if a component is not ready to render.
However I am not understanding how React is checking if a component is ready to render or not. According to this docs
As more data streams in, React will retry rendering, and each time it might be able to progress “deeper”.
Does this mean React also re-renders when data streams in from a network request?
And is <React.Suspense>
constantly checking if a component is ready to render or not?
Upvotes: 14
Views: 4385
Reputation: 361
React.Suspense
relies on Promise with a special wrapper. Practically, we use React.lazy as the wrapper. If you interested to understand how the wrapper works, see the snippet below.
// Boilerplate for the snippet, usually live in index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// Main Component
function App() {
return (
<React.Suspense fallback={<LoadingPage />}>
<RealPage />
</React.Suspense>
);
}
// Promise need to be monitored with a wrapper
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;
}
},
};
}
// This is an example of a delayed process that
// uses `promise` to mock resource fetch
function delayedProcessExample() {
// Wait for 3 seconds
let promise = new Promise((resolve) => setTimeout(resolve, 3000))
// Return an example result
.then(() => "Hello, World!");
return promise;
}
// The delayed process should be executed somewhere.
// If you put it in a component, then the App going to
// request indefinitely
const exampleResource = wrapPromise(delayedProcessExample());
// This is how you access the resource
function RealPage() {
const exampleData = exampleResource.read();
return <div>{exampleData}</div>;
}
// This is the fallback component
function LoadingPage() {
return <div>Loading... Please Wait</div>;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>
Notice the wrapper throws suspender
promise. That expression tells the React.Suspend
there is a promise which need to be waited. Thus, basically React.Suspend
depends on Promise as an Exception to wait the data.
Sources:
Upvotes: 6