Using React.lazy with TypeScript

Viewed 26863

I am trying to use React.lazy for code splitting in my TypeScript React app.

All I am doing is changing that line:

import {ScreensProductList} from "./screens/Products/List";

to this line:

const ScreensProductList = lazy(() => import('./screens/Products/List'));

But the import('./screens/Products/List') part triggers a TypeScript error, stating:

Type error: Type 'Promise<typeof import("/Users/johannesklauss/Documents/Development/ay-coding-challenge/src/screens/Products/List")>' is not assignable to type 'Promise<{ default: ComponentType<any>; }>'.
  Property 'default' is missing in type 'typeof import("/Users/johannesklauss/Documents/Development/ay-coding-challenge/src/screens/Products/List")' but required in type '{ default: ComponentType<any>; }'.

I am not quite sure what I am supposed to do here to get it to work.

6 Answers

You should do export default class {...} from the ./screens/Products/list instead of export class ScreensProductList {...}.

Or, alternatively, you can do:

const ScreensProductList = lazy(() =>
  import('./screens/Products/List')
    .then(({ ScreensProductList }) => ({ default: ScreensProductList })),
);

One option is to add default export in "./screens/Products/List" like that

export default ScreensProductList;

Second is to change import code to

const ScreensProductList = React.lazy(() =>
  import("./screens/Products/List").then((module) => ({
    default: module.ScreensProductList,
  }))
);

Or if you don't mind using an external library you could do:

import { lazily } from 'react-lazily';
const { ScreensProductList } = lazily(() => import('./screens/Products/List'));

Another solution would be:

1. Import using lazy

const ScreensProductList = lazy(() => import('./screens/Products/List'));

2. Set the type on the export

React hooks

import { FunctionComponent /*, FC */ } from 'react';

const List = () => (
  return </>;
);

export default List as FunctionComponent; // as FC;

React class components

import { Component, Fragment, ComponentType } from 'react';

class List extends Component {
  render() {
    return <Fragment />;
  }
}

export default List as ComponentType;

This is the proper syntax. It works also in the Webstorm IDE (the other syntaxes shown here are still showing a warning)

const ScreensProductList = React.lazy(() => import("./screens/Products/List").then(({default : ScreensProductList}) => ({default: ScreensProductList})));
const LazyCart = React.lazy(async () => ({ default: (await import('../Components/market/LazyCart')).LazyCart }))

You can create an index.ts file where you can export all your components like in this eg. :

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

After that you can use React.lazy:

React.lazy(() => import("../components/folder-name-where-the-index-file-is-created").then(({YourComponentName}) => ({default: YourComponentName})))
Related