Intro

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.

Hic Dracones!

If you only care about the codes, check out react-suspense-polyfill, otherwise here we go!

Setting the Stage

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. 😄

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: