Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncaught undefined error when using React.lazy

I'm trying to implement Route-based code splitting as mentioned in the React documentation.

Here's my app before adding lazy implementation. This works fine:

import Counter from "./Counter";
import Home from "./Home";
import Login from "./Login";

export function App() {
  return (
      <Router>
        <Suspense fallback={<div>"Loading.."</div>}>
          <Switch>
            <Route exact path="/" component={Home} />
            <Route exact path="/login" component={Login} />
            <Route exact path="/counter" component={Counter} />
          </Switch>
      </Router>
  );
}

All I changed is I replaced the 3 imports with this:

import { lazy, Suspense } from "react";
const Home = lazy(() => import("./Home"));
const Login = lazy(() => import("./Login"));
const Counter = lazy(() => import("./Counter"));

This code builds successfully but nothing renders on the browser and I get this error in console:

Uncaught undefined
The above error occurred in one of your React components:
    in Unknown (created by Context.Consumer)
    in Route (at App.tsx:29)
    in Switch (at App.tsx:28)
    in Suspense (at App.tsx:27)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.tsx:25)
    in ErrorBoundary (at App.tsx:24)
    in App (at src/index.tsx:19)
    in Provider (at src/index.tsx:18)
    in StrictMode (at src/index.tsx:17)

Am I doing something wrong?

Additional context:

If it matters, the components are named components re-exported as default because that's required by React.lazy:

export { Home as default } from "./Home";

And one of the components uses redux so the App is wrapped in a store provider:

    <Provider store={store}>
      <App />
    </Provider>

Here's my tsconfig:

{
  "compilerOptions": {
    "baseUrl": ".",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "noFallthroughCasesInSwitch": true,
    "target": "es5",
    "module": "esnext"
  },
  "include": [
    "src"
  ]
}

And package versions:

    "react": "^17.0.1",
    "react-dom": "^16.13.1",
    "react-redux": "^7.2.1",
    "react-scripts": "^4.0.1",
    "react-router-dom": "^5.2.0",
    "typescript": "^4.1.2",

Here's source code and possibly related issue on GitHub.

like image 721
Abhijeet Singh Avatar asked Dec 07 '20 14:12

Abhijeet Singh


People also ask

What is React lazy ()?

The React.lazy function lets you render a dynamic import as a regular component.

Does React support lazy loading?

Suppose we have our React application, and we imported the About component into the Home : import AboutUs from './About'; const Home = () => { return ( <div className="App"> <h1>Home Page</h1> <AboutUs /> </div> ); }; export default Home; We can now implement lazy loading by making use of React.

Can we use React lazy in react native?

Yes, It's in React-Native. You can use it for better performance. I hope it will help you to understand!

Why use lazy in React?

The React. lazy() function allows you to render a dynamic import as a normal component. It makes it simple to construct components that are loaded dynamically yet rendered as regular components. When the component is rendered, the bundle containing it is automatically loaded.


2 Answers

After looking at my own question, I figured it out looking at the dependencies. My react and react-dom were on different major versions.

This fixed it: npm i -D [email protected]

like image 105
Abhijeet Singh Avatar answered Oct 01 '22 00:10

Abhijeet Singh


I faced this issue as well, and it turns out that the error was being thrown because I had brackets around my import statement, which meant that I was returning nothing

const MyComponent = React.lazy(() => {
    import('./scenes/MyComponent')
)};

Once I removed the brackets everything worked perfectly, since I was not actually returning something.

const MyComponent = React.lazy(() => 
    import('./scenes/MyComponent')
);
like image 33
Michael M. Avatar answered Oct 01 '22 01:10

Michael M.