0

I am making use of 'react-loadable' in my application to lazy load some of the components that I don't want to render as soon as application loads, currently I am following route based code splitting.

My file structure:

enter image description here

Contents of ignitus-About/Components/index.js are as follows:

export { default as About } from './About';

This is the code snippet of my lazy load AboutUs component:

const AboutUs = Loadable({
  loader: () => import('../ignitus-About/Components/About'),
  loading: Loading,
});

but what you will notice here is that I am writing exact/full path to the About component but inside my Components directory I only have 2 files one index.js and other About.js.

Here index.js is exporting About component by doing this:

export { default as About } from './About';

but when In my Loadable component I write this:

 const AboutUs = Loadable({
      loader: () => import('../ignitus-About/Components'),
      loading: Loading,
    });

It throws an error, so my Question is that does react-lodable expects exact path to the component if not then How can I export my About component from index.js in Loadable component.

entire codebase

So, when I lazy load my component like this:

 const AboutUs = Loadable({
      loader: () => import('../ignitus-About/Components/About'),
      loading: Loading,
    });

it works fine.

If I try lazy loading this like this:

 const AboutUs = Loadable({
      loader: () => import('../ignitus-About/Components'),
      loading: Loading,
    });

it throws an err:

index.js:1452 Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

    Check the render method of `LoadableComponent`.
        in LoadableComponent (created by Route)
        in Route (at publicRoutes.js:56)
        in Switch (at publicRoutes.js:41)
        in div (at publicRoutes.js:39)
        in PublicRoutes (created by Route)
        in Route (at App.js:36)
        in Switch (at App.js:34)
        in div (at App.js:25)
        in App (at src/index.js:29)
        in Router (created by BrowserRouter)
        in BrowserRouter (at src/index.js:28)
        in Provider (at src/index.js:27)
James Z
  • 12,209
  • 10
  • 24
  • 44
Divyanshu Rawat
  • 4,421
  • 2
  • 37
  • 53
  • Can you elaborate on how your code "throws and error"? What were you expecting, and what actually happened? If you got an exception/error, post the line it occurred on and the exception/error details. Please [edit] these details in or we may not be able to help. – Blue Oct 24 '18 at 14:12
  • @FrankerZ I have updated the Question with err and more details. – Divyanshu Rawat Oct 24 '18 at 14:26

1 Answers1

0

The problem is your export { default as About } from './About'; statement. You're exporting no default, so when you use your statement here, it's seeing no default:

loader: () => import('../ignitus-About/Components'),

When the loadable component attempts to import your component, and initialize it with react, it's attempting to do so from the default export of ../ignitus-About/Components. This does not exist. How is the loader supposed to know that you want the About, and not say the Blog component from this import?

Whatever your import may be to loadable, it needs to be a single component. If you have multiple components, you need to use multiple react-loadable's.

Blue
  • 22,608
  • 7
  • 62
  • 92
  • So, if I will have to make it work then what will I have to write? – Divyanshu Rawat Oct 24 '18 at 15:06
  • `loader: () => import('../ignitus-About/Components/About'),` – Blue Oct 24 '18 at 15:07
  • That's what I have mentioned in the Question is there any way to make changes to index.js apart from ``` loader: () => import('../ignitus-About/Components/About'), ``` exporting it like that. – Divyanshu Rawat Oct 24 '18 at 15:10
  • @Div Why are you even trying to create another export layer to begin with? Why is there a Components folder within About Us? And if this is the case, how is your loadable component going to know which component to load, if you have multiple? – Blue Oct 24 '18 at 15:56
  • Because As of now I am not willing to populate index.js with any other component except AboutUs. So, I am not willing to put multiple components inside the component folder except the About.js file. – Divyanshu Rawat Oct 24 '18 at 17:30
  • 1
    You just said you're not willing to put multiple components inside the component folder, so why even have the folder to begin with? Why don't you simply have your each of your main components in the index.js file, under ignitus-About? Take a look [here](https://github.com/react-boilerplate/react-boilerplate/tree/master/app/containers) for an idea of how you should structure your subfolders. There's no reason for a containers subfolder. – Blue Oct 24 '18 at 17:35