使用Typescript AsyncComponent在React中的延迟加载路由

Mik*_*unn 1 lazy-loading dynamic-import typescript reactjs react-router-v4

我试图通过实现AsyncCompoment类来在React中延迟加载路由,如创建React App中的代码拆分所述。以下是本教程中的es6 asyncComponent函数:

import React, { Component } from "react";

    export default function asyncComponent(importComponent) {
      class AsyncComponent extends Component {
        constructor(props) {
          super(props);

          this.state = {
            component: null
          };
        }

        async componentDidMount() {
          const { default: component } = await importComponent();

          this.setState({
            component: component
          });
        }

        render() {
          const C = this.state.component;

          return C ? <C {...this.props} /> : null;
        }
      }

      return AsyncComponent;
    }
Run Code Online (Sandbox Code Playgroud)

我已经在打字稿中编写了此函数,并且可以确认组件确实被延迟加载了。我面临的问题是它们没有被渲染。我能够确定componentDidMount挂钩中的组件对象始终是未定义的:

//AsyncComponent.tsx
async componentDidMount() {
              const { default: component } = await importComponent();

              this.setState({
                component: component
              });
            }
Run Code Online (Sandbox Code Playgroud)

从importComponent函数返回的对象具有以下属性:

{
MyComponent: class MyComponent: f,
__esModule: true
}
Run Code Online (Sandbox Code Playgroud)

我修改了componentDidMount方法以采用此对象的第一个属性,即MyComponent类。进行此更改后,我的项目现在可以延迟加载组件并正确渲染它们。

async componentDidMount() {
          const component = await importComponent();

          this.setState({
            component: component[Object.keys(component)[0]]
          });
        }
Run Code Online (Sandbox Code Playgroud)

我最好的猜测是我没有在打字稿中正确编写此行:

const { default: component } = await importComponent();
Run Code Online (Sandbox Code Playgroud)

我像这样调用asyncComponent方法:

const MyComponent = asyncComponent(()=>import(./components/MyComponent));
Run Code Online (Sandbox Code Playgroud)

有人知道如何在打字稿中实现AsyncComponent吗?我不确定在esModule对象上简单地获取0索引是否是正确的方法。

Mik*_*unn 6

弄清楚了,所需要做的就是导出要延迟加载的所有Component类的默认值。这是我完整的解决方案:

//AsyncComponent.tsx
import * as React from "react";

interface AsyncComponentState{
    Component: any;
}
export default function asyncComponent(getComponent: any): any  {
    class AsyncComponent extends React.Component<{},AsyncComponentState> {


        constructor(props: any) {
            super(props);

            this.state = {
                Component: null
            };
        }

        async componentDidMount(){
            const {default: Component} = await getComponent();
            this.setState({
                Component: Component
            });


        }


        render() {
            const C = this.state.Component;
            return C ? <C {...this.props}/> : <div>....Loading</div>
        }
    }
    return AsyncComponent;

}
//Counter.tsx
import * as React from 'react';
import { RouteComponentProps } from 'react-router';

interface CounterState {
    currentCount: number;
}

 class Counter extends React.Component<RouteComponentProps<{}>, CounterState> {
    constructor() {
        super();
        this.state = { currentCount: 0 };
    }

    public render() {
        return <div>
            <h1>Counter</h1>

            <p>This is a simple example of a React component.</p>

            <p>Current count: <strong>{ this.state.currentCount }</strong></p>

            <button onClick={ () => { this.incrementCounter() } }>Increment</button>
        </div>;
    }

    incrementCounter() {
        this.setState({
            currentCount: this.state.currentCount + 1
        });
    }
}
export default Counter;

//routes.tsx
import * as React from 'react';
import {Route} from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import asyncComponent from './components/AsyncComponent';


const AsyncCounter =  asyncComponent(() =>  import('./components/Counter'));

export const routes = <Layout>
    <Route exact path='/' component={ Home } />
    <Route path='/counter' component={ AsyncCounter } />
</Layout>;
Run Code Online (Sandbox Code Playgroud)