Lazy load component with react && react-router.
rrr-lazy requires React 16.2.0 or later.
For npm:
npm install rrr-lazy
For yarn:
yarn add rrr-lazy
IntersectionObserver is required by this library. You can use this polyfill for old browsers https://github.com/w3c/IntersectionObserver/tree/master/polyfill
import React from 'react';
import { Lazy } from 'rrr-lazy';
const MyComponent = () => (
<div>
<Lazy
rootMargin="300px 0 300px 0"
render={(status) => (
if (status === 'unload') {
return <div>Unload</div>
}
if (status === 'loading') {
return <div>Loading</div>
}
if (status === 'loaded') {
return (
<img
style={{ height: 762, width: 1024 }}
src={ status === 'loaded' ? 'http://apod.nasa.gov/apod/image/1502/HDR_MVMQ20Feb2015ouellet1024.jpg' : `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg"/>')}`}
/>
);
}
throw new Error('Unknown status');
)}
/>
</div>
);
import { lazy } from 'rrr-lazy';
async function onLoading() {
// Loading data;
// ...
return data;
}
async function onLoaded() {
// Do something on loaded
// ...
return result;
}
async function onUnload() {
// Do something on unload
// ...
return result;
}
async function onError(error) {
// Do something on error
console.error(error);
// ...
return result;
}
class App extends React.Component {
render() {
// the matched child route components become props in the parent
return (
<Lazy
rootMargin="300px 0 300px 0"
render={(status) => (
if (status === 'unload') {
return <div>Unload</div>
}
if (status === 'loading') {
return <div>Loading</div>
}
if (status === 'loaded') {
return (
<img
style={{ height: 762, width: 1024 }}
src={ status === 'loaded' ? 'http://apod.nasa.gov/apod/image/1502/HDR_MVMQ20Feb2015ouellet1024.jpg' : `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg"/>')}`}
/>
);
}
throw new Error('Unknown status');
)}
onLoading={onLoading}
onLoaded={onLoaded}
onUnload={onUnload}
onError={onError}
/>
)
}
}
API: <Lazy root rootMargin render loaderComponent loaderProps onError onLoaded onUnload onUnloaded />
Type: String|HTMLElement
Default: null
This value will be used as root for IntersectionObserver (See root.
Type: String
Default: null
This value will be used as rootMargin for IntersectionObserver (See rootMargin.
Type: Function
Required
status
can be unload
, loading
, loaded
.
props
are props that passed from Lazy
. This is designed for @lazy
, and when you use <Lazy>
component, you may not need it.
Type: string
Default: div
Type: string
Default: {}
loaderComponent
and loaderProps
is used to create a LoaderComponent when status is unload
or loaded
.
The result of render(status, props)
will be passed to LoaderComponent as children
.
Usage:
@routerHooks({
fetch: async () => {
await fetchData();
},
defer: async () => {
await fetchDeferredData();
},
})
@lazy({
render: (status, props, Component) => {
if (status === 'unload') {
return <div style={{ height: 720 }}>Unload</div>;
} else if (status === 'loading') {
return <div style={{ height: 720 }}>Loading</div>;
} else {
return <Component {...props} />;
}
},
onLoaded: () => console.log('look ma I have been lazyloaded!')
})
class MyComponent extends React.Component {
render() {
return (
<div>
<img src='http://apod.nasa.gov/apod/image/1502/HDR_MVMQ20Feb2015ouellet1024.jpg' />
</div>
);
}
}
Or
class MyComponent extends React.Component {
render() {
return (
<div>
<img src='http://apod.nasa.gov/apod/image/1502/HDR_MVMQ20Feb2015ouellet1024.jpg' />
</div>
);
}
}
const myComponent = lazy({
render: (status, props, Component) => {
if (status === 'unload') {
return <div style={{ height: 720 }}>Unload</div>;
} else if (status === 'loading') {
return <div style={{ height: 720 }}>Loading</div>;
} else {
return <Component {...props} />;
}
},
onLoaded: () => console.log('look ma I have been lazyloaded!')
})(MyComponent);
With webpack 2 import()
const myComponent = lazy({
render: (status, props, Component) => {
if (status === 'unload') {
return <div style={{ height: 720 }}>Unload</div>;
} else if (status === 'loading') {
return <div style={{ height: 720 }}>Loading</div>;
} else {
return <Component {...props} />;
}
},
onLoaded: () => console.log('look ma I have been lazyloaded!'),
getComponent: () => import('./MyComponent'),
})();
You can optionally use LazyProvider
and pass a version (such as location) to the value
prop.
All of the Lazy instances will be reset when version changed.
Example:
class Application extends React.Component {
render() {
// when pathname changed, all of the Lazy instances will be reset.
const { pathname, children } = this.state;
<LazyProvider value={pathname}>
{ children }
</LazyProvider>
}
}
MIT