Reputation: 524
I've a condition where I've 3 components
A.js B.js C.js
In old code
routes.js
const A = lazy(() => import("../test/A"));
const B = lazy(() => import("../test/B"));
const C = lazy(() => import("../test/C"));
<Route
path="/test"
render={({ match: { url } }) => (
<Switch>
<Route exact path={`${url}/a-test`} component={A} />
<Route exact path={`${url}/b-test`} component={B} />
<Route exact path={`${url}/c-test`} component={C} />
</Switch>
)}
/>
What I want to achieve
By the above code we can conclude that every time the separate builds for A, B, C will get download due to lazy load, but I want to achieve a functionality where I can download all 3 of them altogether, i.e. When a download a single component using that only I can download all three of them as a single separate build
What I tried - New Code
combine_module.js
import A from "./A";
import B from "./B";
import C from "./C";
const test = {A, B, C};
export default test;
routes.js
const Test = lazy(() => import("../test/combine_module"));
<Route
path="/test"
render={({ match: { url } }) => (
<Switch>
<Route exact path={`${url}/a-test`} component={Test.A} />
<Route exact path={`${url}/b-test`} component={Test.B} />
<Route exact path={`${url}/c-test`} component={Test.C} />
</Switch>
)}
/>
Code
My Issue
I don't know about the approach whether it's wrong or right as I'm not getting any error or any warning related to this in the console but seeing a blank screen cannot see the output, So can please anybody tell how to make this thing right and achieve the desired functionality.
Upvotes: 3
Views: 4312
Reputation: 3230
According to the React.lazy documentation:
React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.
So the result of React.lazy
is not a module but a special object Suspense
can work with.
A usual module can be loaded lazily with WebPack's dynamic import. There is a tricky part with this because the module can be loaded after the component was rendered. So two things we need to do:
1) ensure the component does not render undefined
while module is being loaded
2) update the component when the module has been loaded
Updating is quite simple we can make a hook that will set the module as state on load
function useDynamicModule(path) {
const [module, setModule] = useState({});
const [error, setError] = useState();
useEffect(() => {
import(path).then(setModule, setError);
}, []);
return error ? { $error: error } : module.default
}
Usage:
export default function App() {
const Test = useDynamicModule("./CombineModule");
if (!Test) return null;
if (Test.$error) return "Error";
return (
<Router history={history}>
// ...
</Router>
);
}
Upvotes: 2