2

I'm trying to implement a "lazy-route" to achieve code splitting in my React single page app.

  • It's all client side rendered
  • I'm using react-router
  • Also using Webpack

I have this component that renders all my routes.

AllRoutes.js

function AllRoutes() {
  return(
    <Switch>
      <Route exact path={"/ROUTE_A"} component={Component_A}/>
      <Route exact path={"/ROUTE_B"} component={Component_B}/>
      // AND SO ON
    </Switch>
  );
}

I'm trying to do something like this:

import LazyRoute from './LazyRoute';

function AllRoutes() {
  return(
    <Switch>
      <Route exact path={"/ROUTE_A"} component={Component_A}/>
      <Route exact path={"/ROUTE_B"} component={Component_B}/>
      <Route exact path={"/ROUTE_C"} component={LazyRoute}/>  // THIS SHOULD LAZY LOAD
    </Switch>
  );
}

And this is what I've tried:

LazyRoute.js

function LazyRoute() {
  return import("@pages/Component_C").then(({default: Component_C}) => {
    return Component_C;
  });
}

export default LazyRoute;

Webpack seems to be doing its part in splitting this LazyRoute bundle:

enter image description here

But I'm getting this error:

enter image description here

I know I'm retuning a Promise by doing return import(). But isn't this the whole point?

cbdeveloper
  • 27,898
  • 37
  • 155
  • 336
  • You can use react lazy here...why not using it ? – jossefaz Jul 02 '20 at 06:38
  • @yAzou I know.. I will probably use `React.lazy` or `Loadable`, but I like to do a raw implementation so I can understand it better. – cbdeveloper Jul 02 '20 at 06:41
  • I was able to make this work at some point, but I completely forgot how I did it. Tried to look up in old files but couldn't find it. – cbdeveloper Jul 02 '20 at 06:42
  • I can post an example of your implementation using react lazy if you wish – jossefaz Jul 02 '20 at 06:42
  • Thanks, I haven't tried with `React.lazy` yet. I'll upvote it, but I'm still looking for the "raw" solution, using only dynamic imports. – cbdeveloper Jul 02 '20 at 06:46
  • @yAzou I FOUND IT!!! lol.. I'll post how I did this the last time. Thanks for your help. You can also post the `React.lazy` version if you want. – cbdeveloper Jul 02 '20 at 06:50
  • OKay, i already posted an example with react lazy if you want too, you can try it – jossefaz Jul 02 '20 at 06:51

2 Answers2

3

Hi you can use React Lazy here. Here is an example that should work using your implementation.

import React, { lazy } from "react";
import { Route, Switch } from "react-router-dom";
import LazyRoute from './LazyRoute';

const Component_C = lazy(() => import("./Component_C"));

function AllRoutes() {
  return (
<Switch>
  <Route exact path={"/ROUTE_A"} component={Component_A}/>
  <Route exact path={"/ROUTE_B"} component={Component_B}/>
  <Route exact path={"/ROUTE_C"} component={LazyRoute(Component_C)}/>  // THIS SHOULD LAZY LOAD
</Switch>
  );
}

LazyRoute.js

import React, { Suspense } from "react";

function LazyRoute(Component) {
  return props => (
    <Suspense fallback={<div>Loading...</div>}>
      <Component {...props} />
    </Suspense>
  );
}
export default LazyRoute;
jossefaz
  • 3,312
  • 4
  • 17
  • 40
1

Just found an old solution that I wrote for this.

import React, { useEffect, useState } from 'react';
import styled from 'styled-components';

const LS = {};

LS.Container_DIV = styled.div`
`;

async function lazyRender() {
  const TestContainer = (await import("@pages/Test/TestContainer"));
  return new Promise((resolve) => {
    resolve(TestContainer);
  });
}

function LazyRoute(props) {
  console.log('Rendering LazyRoute...');

  const [lazyLoading,setLazyLoading] = useState(true);
  const [LazyComponent,setLazyComponent] = useState(null);

  useEffect(() => {
    async function getLazyComponent() {
      const component = await lazyRender();
      setLazyComponent(component);
      setLazyLoading(false);
    }
    getLazyComponent();
  },[]);

  return(
    lazyLoading ?
      <div>I am Lazy Loading....</div>
    : <LazyComponent.default {...props}/>
  );
}

export default React.memo(LazyRoute);
cbdeveloper
  • 27,898
  • 37
  • 155
  • 336