preface

Suspense, as it literally is, puts components into a “hover” state when they encounter asynchronous operations and comes back to normal when the asynchronous operations have a result.

Asynchronous operations fall into two simple categories:

  1. Asynchronous loading code
  2. Asynchronously loading data

Asynchronous loading code

Asynchronously loading code is called code splitting, and it should look something like this:

import React, {lazy, Suspense} from 'react';

const OtherComponent = lazy((a)= > import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>} ><OtherComponent />
    </Suspense>
  );
}
Copy the code

It is worth mentioning that the current version (as of [email protected]) does not support server-side rendering, but it will be supported in a future version.

Asynchronously loading data

Suspense asynchronous loading data is currently unstable. According to the React 16.x Roadmap, it will be released in mid-2019, but React has a standalone package called React-Cache. Using it in conjunction with [email protected] gives us a taste of Suspense for asynchronously loading data.

import { unstable_createResource } from 'react-cache';

const getSomething = (something) = > new Promise((resolve) = > {
  setTimeout((a)= > {
    resolve(something);
  }, 1000);
})

const resource = unstable_createResource((id) = > getSomething(id))

function Demo() {
  const data = resource.read(Awesome!)
  return (
    <div>{data}</div>
  );
}
Copy the code

Details of Suspense

In the example above, the Suspense component passes in the fallback property, which is used to display the page being loaded, commonly known as loading.

So we are thinking about a problem, if an asynchronous data request process is very fast, this will cause the loading screen to flash, resulting in a flash screen.

Suspense gives a solution for this situation with the maxDuration attribute:

<Suspense fallback={<Spinner />} maxDuration={500}>
  // ...
</Suspense>
Copy the code

Fallback is displayed when the asynchronous data acquisition time is longer than maxDuration; otherwise, data is displayed directly.

Note that the maxDuration attribute is valid only in Concurrent Mode. In previous Sync Mode, maxDuration is always 0.

// ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM
  .unstable_createRoot(document.getElementById('root'))
  .render(
    <React.unstable_ConcurrentMode>
      <App />
    </React.unstable_ConcurrentMode>
  );
Copy the code

The principle of

Suspense’s implementation principle is quite controversial.

When we write asynchronous request data in Render, we throw an exception, of course it should be a promise, and this exception will be caught by a new life cycle in Suspense ComponentDidCatch, In Suspense the child components are rendered as loading during this life cycle, and when the asynchronous request ends and loading ends, the normal component returns.

Unstable_createResource throws a suspender object in Pending, which is a Promise.

function unstable_createResource(fetch, maybeHashInput) {
  // ...
  var resource = {
    read: function (input) {
      // ...
      var key = hashInput(input);
      var result = accessResult(resource, fetch, input, key);
      switch (result.status) {
        case Pending:
          {
            var suspender = result.value;
            throw suspender;
          }
        case Resolved:
          {
            var _value = result.value;
            return _value;
          }
        case Rejected:
          {
            var error = result.value;
            throw error;
          }
        default:
          // Should be unreachable
          return undefined; }},// ...
  };
  return resource;
}
Copy the code

conclusion

I do not know if you can accept the implementation of such a hack, although there are shortcomings, but it brings convenience really let me look forward to.

Reference:

  • The One with Concurrent Mode
  • React Supense vs. asynchronous rendering
  • React: Suspense implementation and discussion
  • Don’t React Suspense