If you love React, you’ve probably heard something about the upcoming Suspense APIs, but even after watching a demo or two, it was pretty difficult for me to lay my finger on how exactly Suspense works.
So I put my computer science cap on and decided to try and recreate it with the current version of React v16.
A few disclaimers before we get started that my fictional legal team wants to get out of the way.
The actual version of Suspense that will ship with React is significantly more complicated and efficient than the version in this polyfill. This tutorial & accompanying module are meant mainly for learning and experimental purposes. Also, the current polyfill will likely not play well with SSR.
If you only care about the codes, check out react-suspense-polyfill, otherwise here we go!
IMHO, Suspense is a very powerful addition to the core React API surface, and I believe it will have a profound effect on how pragmatic React code is written a few years from now.
If you take nothing else away from this article, understand this:
At its core, React Suspense works by allowing an async component to throw a Promise from its render method.
This polyfill mimics React’s internal support for this behavior by implementing an error boundary in the Timeout component. If the error boundary encounters a thrown Promise, it waits until that Promise resolves and then attempts to re-render its children. It also handles falling back to loading content if the Promise takes too long to resolve. (explained in detail below)
I hope this module and accompanying demos make it easier to get up-to-speed with React Suspense. 😄
import React from 'react'
import PropTypes from 'prop-types'
import Timeout from './timeout'
export default function Suspense (props) {
const {
delayMs,
fallback,
suspense,
children
} = props
return (
<Timeout ms={delayMs} suspense={suspense}>
{didExpire => (didExpire ? fallback : children)}
</Timeout>
)
}
Suspense.propTypes = {
delayMs: PropTypes.number,
fallback: PropTypes.node,
suspense: PropTypes.node,
children: PropTypes.node
}
Suspense.defaultProps = {
fallback: null,
suspense: null,
children: null
}
Suspense is the main public-facing component exposed by React Suspense. Its interface is relatively straightforward, exposing the following props:
delayMs - Amount of time in milliseconds to wait before displaying fallback / loading content. The main reason for adding a delay before displaying fallback content is to prevent loading indicators flashing too quickly before the main async content loads which can be an annoying UI distraction.fallback - A React Node that will be displayed while any child component is loading only after delayMs have elapsed. This will typically be some type of loading spinner.suspense - A React Node that will be displayed while any child component is loading only before delayMs have elapsed. Note: this optional prop is specific to react-suspense-polyfill and is strictly for the purpose of demoing how suspense works.children - A React Node that represents the main content of this Suspense component which may or may not throw a Promise while loading asynchronous resources. See react-async-elements for some examples of super sexy, async-friendly child components.