React 中的延迟加载路由与 Typescript AsyncComponent
Lazy Loading Routes in React With Typescript AsyncComponent
我正在尝试通过实现 AsyncCompoment class 在 React 中延迟加载路由,如此处 Code Splitting in Create 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;
}
我已经用 typescript 编写了这个函数,可以确认组件确实是延迟加载的。我面临的问题是它们没有被渲染。我能够确定组件对象在 componentDidMount 挂钩中始终未定义:
//AsyncComponent.tsx
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
从 importComponent 函数返回的对象具有以下属性:
{
MyComponent: class MyComponent: f,
__esModule: true
}
我修改了 componentDidMount 方法以获取此对象的第一个 属性,即 MyComponent class。进行此更改后,我的项目现在可以延迟加载组件并正确渲染它们。
async componentDidMount() {
const component = await importComponent();
this.setState({
component: component[Object.keys(component)[0]]
});
}
我最好的猜测是我没有用打字稿正确地写下这一行:
const { default: component } = await importComponent();
我这样调用 asyncComponent 方法:
const MyComponent = asyncComponent(()=>import(./components/MyComponent));
有人知道如何在打字稿中实现 AsyncComponent 吗?我不确定简单地获取 esModule 对象上的 0 索引是否是正确的方法。
// AsyncComponent.tsx
import * as React from "react";
interface AsyncComponentState {
Component: null | JSX.Element;
};
interface IAsyncComponent {
(importComponent: () => Promise<{ default: React.ComponentType<any> }>): React.ComponentClass;
}
const asyncComponent: IAsyncComponent = (importComponent) => {
class AsyncFunc extends React.PureComponent<any, AsyncComponentState> {
mounted: boolean = false;
constructor(props: any) {
super(props);
this.state = {
Component: null
};
}
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />
});
}
}
render() {
const Component = this.state.Component;
return Component ? Component : <div>....Loading</div>
}
}
return AsyncFunc;
}
export default 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>;
我正在尝试通过实现 AsyncCompoment class 在 React 中延迟加载路由,如此处 Code Splitting in Create 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;
}
我已经用 typescript 编写了这个函数,可以确认组件确实是延迟加载的。我面临的问题是它们没有被渲染。我能够确定组件对象在 componentDidMount 挂钩中始终未定义:
//AsyncComponent.tsx
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
从 importComponent 函数返回的对象具有以下属性:
{
MyComponent: class MyComponent: f,
__esModule: true
}
我修改了 componentDidMount 方法以获取此对象的第一个 属性,即 MyComponent class。进行此更改后,我的项目现在可以延迟加载组件并正确渲染它们。
async componentDidMount() {
const component = await importComponent();
this.setState({
component: component[Object.keys(component)[0]]
});
}
我最好的猜测是我没有用打字稿正确地写下这一行:
const { default: component } = await importComponent();
我这样调用 asyncComponent 方法:
const MyComponent = asyncComponent(()=>import(./components/MyComponent));
有人知道如何在打字稿中实现 AsyncComponent 吗?我不确定简单地获取 esModule 对象上的 0 索引是否是正确的方法。
// AsyncComponent.tsx
import * as React from "react";
interface AsyncComponentState {
Component: null | JSX.Element;
};
interface IAsyncComponent {
(importComponent: () => Promise<{ default: React.ComponentType<any> }>): React.ComponentClass;
}
const asyncComponent: IAsyncComponent = (importComponent) => {
class AsyncFunc extends React.PureComponent<any, AsyncComponentState> {
mounted: boolean = false;
constructor(props: any) {
super(props);
this.state = {
Component: null
};
}
componentWillUnmount() {
this.mounted = false;
}
async componentDidMount() {
this.mounted = true;
const { default: Component } = await importComponent();
if (this.mounted) {
this.setState({
component: <Component {...this.props} />
});
}
}
render() {
const Component = this.state.Component;
return Component ? Component : <div>....Loading</div>
}
}
return AsyncFunc;
}
export default 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>;