6

I'm trying to use React.lazy to lazy load a React Component. The component looks like this:

function App() {
const HubScreen = React.lazy(() => import("./screens/hub").then((mod) => {
    console.log(mod.default)
    return mod.default;
}));

return (
    <BrowserRouter>
        <MuiThemeProvider theme={theme}>
            <MainContaier>
                <div id="screen">
                    <CssBaseline />
                    <Switch>
                        <React.Suspense fallback={<h1>Loading...</h1>}>
                            <Route exact path="/" component={HomeScreen} />
                            <Route path="/hub" render={() => <HubScreen />} />
                        </React.Suspense>
                    </Switch>
                </div>
            </MainContaier>
        </MuiThemeProvider>
    </BrowserRouter >
) 
}

And this is the component I'm importing

import React from "react";

function HubScreen() {
  return (
      <div>Hi</div>
  );
}

export default HubScreen;

When I navigate to /hub I see the value of mod.default as undefined. Along with my Chrome window becoming completely unresponsive, requiring a force stop.

I know that my path to the module ./screens/hub, is correct because, if I put a fake path like ./screens/hube then webpack gives me the error:

 Module not found: Error: Can't resolve './screens/hube' in '/home/travis/Workspace/avalon/assets/js'

I'm stumped haven't found a similar problem anywhere.

This answer gave me some insight as to why my browser was hanging up. However I still seem to have the same root problem; the undefined module.default. After changing the root component to this:

const HubScreen = React.lazy(() => import("./screens/hub"));

function App() {
return (
    <BrowserRouter>
        <MuiThemeProvider theme={theme}>
            <MainContaier>
                <div id="screen">
                    <CssBaseline />
                    <Switch>
                        <React.Suspense fallback={<h1>Loading...</h1>}>
                            <Route exact path="/" component={HomeScreen} />
                            <Route path="/hub" component={HubScreen} />
                        </React.Suspense>
                    </Switch>
                </div>
            </MainContaier>
        </MuiThemeProvider>
    </BrowserRouter >
)
}

I get the War:

Warning: lazy: Expected the result of a dynamic import() call. Instead received: [object Object]

Your code should look like: 
  const MyComponent = lazy(() => import('./MyComponent'))

And then the error:

Uncaught Error: Element type is invalid. Received a promise that resolves to: undefined. Promise elements must resolve to a class or function.

Which I have taken to mean that undefined is being returned from the import resolution, as the console.log seems to confirm.

0

2 Answers 2

12

Also another possibility of getting this error is by missing the default export in your Component which becomes a named export.

This syntax is only supported for Default exports.

const HubScreen = React.lazy(() => import("./screens/hub"));

import React, {useState} from 'react';

const ChangeName = (props) => {

    return (
    <div>

      <p>Name: {props.name}</p>
      <p>Email: {props.email}</p>

      <div>
        <button onClick={()=>props.changeStatus()}>Change Details</button>
      </div>
    </div>
    )
  }


  export default ChangeName; ====> By missing the default Export
Sign up to request clarification or add additional context in comments.

Comments

1

First off, move your const HubScreen outside of your component. When App() rerenders, it will cause an infinate loop to keep trying to load HubScreen over and over again. Secondly, just use () => import... and let React.lazy use the default component exported. Additionally, you should not need to use render for the route. Just provide the component:

const HubScreen = React.lazy(() => import("./screens/hub"));

function App() {

return (
    <BrowserRouter>
        <MuiThemeProvider theme={theme}>
            <MainContaier>
                <div id="screen">
                    <CssBaseline />
                    <Switch>
                        <React.Suspense fallback={<h1>Loading...</h1>}>
                            <Route exact path="/" component={HomeScreen} />
                            <Route path="/hub" component={HubScreen} />
                        </React.Suspense>
                    </Switch>
                </div>
            </MainContaier>
        </MuiThemeProvider>
    </BrowserRouter >
    ) 
}

8 Comments

The reloading of ./screens/hub explains why my browser is hanging up. But I still have the problem of the default export being undefined. I added the then so I could log out what was going on with the import. With the code above I get an error that seems to be complaining about the default export being undefined. I'll add it to the question.
@TravisSmith console.log(HubScreen) right before the export. Make sure you have no typos, and tell me what you see in the console when it tries to load.
It doesn't even hit the log at all. I changed to const HubScreen = require("./screens/hub") and then I saw the log: ƒ HubScreen() { return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, "Hi"); }. But when using React.lazy log doesn't get called at all. Additionally this might be relevant. Using the require syntax gives me the same error. But, using import HubScreen from "./screens/hub" renders the component.
Try: const HubScreen = React.lazy(() => require("./screens/hub"));
If I do that I see the log but I get an error: Uncaught null and later Uncaught TypeError: _thenable.then is not a function
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.