Created
August 10, 2019 10:46
-
-
Save karpolan/80cf28cb742851fcb3abb7796c4f7fdc to your computer and use it in GitHub Desktop.
withSuspense() HOC for React.lazy() + React.Suspense
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { CircularProgress, LinearProgress } from '@material-ui/core/'; | |
/** | |
* Wraps the React Component with React.Suspense and FallbackComponent while loading. | |
* @param {React.Component} WrappedComponent - lazy loading component to wrap. | |
* @param {React.Component} FallbackComponent - component to show while the WrappedComponent is loading. | |
*/ | |
export const withSuspense = (WrappedComponent, FallbackComponent = null) => { | |
return class extends React.Component { | |
render() { | |
if (!FallbackComponent) FallbackComponent = <LinearProgress />; // by default | |
return ( | |
<React.Suspense fallback={FallbackComponent}> | |
<WrappedComponent {...this.props} /> | |
</React.Suspense> | |
); | |
} | |
}; | |
}; | |
... | |
// Usage | |
const lazySomeComponent = React.lazy(() => import('./xxx/SomeComponent')); | |
export const SomeComponent = withSuspense(lazySomeComponent); | |
export const SomeComponentWithCircularProgress = withSuspense(lazySomeComponent, <CircularProgress />); | |
export const SomeComponentWithDiv = withSuspense(lazySomeComponent, <div>Loading...</div>); |
Could be :)
@karpolan could you please help me ? Can I move import
logic into the HOC ? I mean to move const lazySomeComponent = React.lazt(() => import('path'));
into the withSuspense
method?
You can, but in that case you need await loading...
I suggest to use following way:
import React from 'react';
/**
* Note: Don't import/export all Views directly, use lazy loading!
*/
import { withSuspense } from '../components';
import NotFound from './NotFound';
/**
* Views/Pages with Lazy Loading
*/
const Welcome = withSuspense(React.lazy(() => import('./Welcome')));
const About = withSuspense(React.lazy(() => import('./About')));
const MyProfile = withSuspense(React.lazy(() => import('./MyProfile')));
export { NotFound, Welcome, MyProfile, About };
@karpolan many thanks!
Nice! A comment on the naming - the argument you pass to Suspense
's fallback
prop is not actually a React component - it's a tree of React elements, in TS typed as ReactNode
. So the naming FallbackComponent
(capitalised, with "Component") is actually misleading - note you never write <FallbackComponent />
. A better name for the second argument of the HOC would be simply fallback
, or fallbackElement
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey, thanks for this!
I have small suggestion: you can replace
null
with<LinearProgress />
in...withSuspense = (WrappedComponent, FallbackComponent = <LinearProgress />) => ....
and you can get rid of check if its null
if (!FallbackComponent) FallbackComponent = <LinearProgress />; // by default