Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React lazy with TypeScript and Redux

I have a problem with combining React lazy with my project that uses TypeScript and Redux. Here is my code:

// lazy-area.tsx
const LazyArea = ({text}: Props): JSX.Element => {
    ....
};

export const LazyArea = connect(
mapStateToProps,
mapDispatchToProps
)(LazyArea);


//Menu.tsx
import React, { lazy, Suspense } from 'react';
....
const lazyArea = lazy(() => import('./lazy-area'));

const Menu = ({
    .....
  }: Props): JSX.Element | null => {
      return (
        <Suspense fallback={LoadingView}>
            <LazyArea />
        </Suspense>
      )
    export const Menu = connect(
    mapStateToProps,
    mapDispatchToProps
    )(Menu);
});

With this set up I get an error saying:

Type 'Promise<typeof import("/home/user/app/lazy-area")>' is not assignable to type 'Promise<{ default: ComponentType<any>; }>'.
  Property 'default' is missing in type 'typeof import("/home/user/app/src/lazy-area")' but required in type '{ default: ComponentType<any>; }'.

I have tried solutions presented in: TypeScript with React Lazy getting promise error to add export as ComponentType<any> and export as React.FC to LazyArea export but error stays the same.

The solution presented in here removes the error but according to this the solution is def not best practice and "may kill optimizations and potentially result in infinite loop".

This error also goes away when using export default in LazyArea:

const LazyArea = connect(
mapStateToProps,
mapDispatchToProps
)(LazyArea);

export default LazyArea;

However I have read from some sources that using export default should be avoided.

Is there any good solution to get past this problem? Please inform if I have presented too little info about something. Thanks :)

like image 942
Anni Puurunen Avatar asked Nov 07 '22 08:11

Anni Puurunen


1 Answers

I don't know why you think using default exports should be avoided :) I think it's just a convention that some teams have. So adding export default LazyArea; is a valid way to deal with this. You won't have too many lazy modules anyway.

That's why the solution from React docs could also work where you just put that default export into its own file.

The other recommended approach is to change import code to convert it to default inline:

const LazyArea = React.lazy(() =>
  import("./lazy-area").then((module) => ({
    default: module.LazyArea,
  }))
);

But that's seems like too much work for me :) So I created react-lazily which does what you would expect.

Example

const { LazyArea } = lazily(() => import('./lazy-area'));

it's just a small wrapper around React.lazy, but it allows you to have a really straight forward code, like that:

import { lazily } from 'react-lazily';
const { Component1, Component2 } = lazily(() => import('./Components'))
like image 92
JLarky Avatar answered Nov 14 '22 22:11

JLarky