// Create Lazy Component
const LazyComponent = React.lazy(() => import('./SomeOtherComponent'));
ReactDOM.hydrate(
<React.unstable_Suspense fallback="loading">
<LazyComponent />
</React.unstable_Suspense>
, element
);
await LazyComponent;
// Done!
React.lazy
で作った非同期コンポーネントを React.Suspense で囲むと非同期処理が行われる。
びっくりするのは、 React.lazy で作ったコンポーネントを await できる (内部的には then が実装してある)
await を待つとDOMへの適用処理を待って表示できる。読む限りはこのテストは ReactDOMServer ではなく ReactDOM + jsdom on Node.js なのだが、jsdom なしで動くようにできるかは不明。
SSRを実装する人は内部の非同期処理の promise をかき集めて、Promise.all することになりそう
packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
it('should be able to use lazy components after hydrating', async () => {
async function fakeImport(result) {
return {default: result};
}
const Lazy = React.lazy(
() =>
new Promise(resolve => {
setTimeout(
() =>
resolve(
fakeImport(function World() {
return 'world';
}),
),
1000,
);
}),
);
class HelloWorld extends React.Component {
state = {isClient: false};
componentDidMount() {
this.setState({
isClient: true,
});
}
render() {
return (
<div>
Hello{' '}
{this.state.isClient && (
<React.unstable_Suspense fallback="loading">
<Lazy />
</React.unstable_Suspense>
)}
</div>
);
}
}
const element = document.createElement('div');
element.innerHTML = ReactDOMServer.renderToString(<HelloWorld />);
expect(element.textContent).toBe('Hello ');
ReactDOM.hydrate(<HelloWorld />, element);
expect(element.textContent).toBe('Hello loading');
jest.runAllTimers();
await Lazy;
expect(element.textContent).toBe('Hello world');
を読む限りわかること