TypeScript,React.ReactNode,withRouter和连接

时间:2019-01-04 21:38:31

标签: reactjs typescript react-redux react-router-dom

更新2 根据{{​​3}}的第二条评论,我可以通过更改来解决我的问题

component: <TestRoute />

component: TestRoute

更新 根据{{​​3}}的评论,我将代码修改为以下代码,并且我遇到的错误已经消失,但是这次我在分配给组件的构造函数中将其替换为新的错误属性:

  

[加载器]中的错误。/src/ts/components/app/StandardRouter.tsx:34:13       TS2322:类型'Element'不能分配给类型'ComponentClass | FunctionComponent”。     类型“元素”不可分配给类型“功能组件”。       类型'Element'不提供签名'(props:any,context ?: any)的匹配:ReactElement |空”。

StandardRouter.tsx

// React router component. Connects all routes to the application.
import * as React from 'react';
import { connect } from 'react-redux';
import { Route, Switch, withRouter } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import { IntlProvider } from 'react-intl';
import _forEach from 'lodash/forEach';
import _find from 'lodash/find';
import { History, createHashHistory } from 'history';
import { connectRouter } from 'connected-react-router';
import reducerRegistry from '../../api/private/core/reducer-registry';
import routeRegistry from '../../api/private/core/route-registry';
import RouteObject from '../../interfaces/route-object';
import TestRoute from '../test/test-route';

class StandardRouter extends React.Component {
    constructor(props: object) {
        super(props);
        this._history = createHashHistory();
        reducerRegistry.register({
            name: 'router',
            key: 'cb3dceb0-367b-4c2a-a0fb-a8d8671283e2',
            reducer: connectRouter(this._history)
        });
        routeRegistry.setChangeListener(() => {
            if (this._isMounted) {
                this.forceUpdate();
            } else if (!this._isMounted && !this._doUpdate) {
                this._doUpdate = true;
            }
        });
        routeRegistry.register({
            key: '90e8246f-96a6-49a5-920a-a2cf0d347fcd',
            component: <TestRoute />, // <-- New error here
            paths: '/',
            text: 'Test 123'
        });
    }

    componentDidMount(): void {
        this._isMounted = true;
        if (this._doUpdate) {
            this.forceUpdate();
        }
    }

    private _history: History;
    private _isMounted: boolean = false;
    private _doUpdate: boolean = false;

    chooseRender(path: string, Comp: React.ComponentType): React.ReactNode {
        return <Comp />;
    }

    // Creates Route objects based on routes collection from registry
    renderPages(): React.ReactNode[] {
        const routes: React.ReactNode[] = [];
        const loadedRoutes: RouteObject[] = routeRegistry.getRoutes();
        _forEach(loadedRoutes, page => {
            const Component = withRouter(
                connect<any, any, any>(() => ({
                    pageid: page.pageId
                }))(page.component) // <-- Error on this line, on page.component.
            );
            if (Array.isArray(page.paths)) {
                // Multiple paths available for a single route. For example "/" and "/Home" for the
                // home page.
                _forEach(page.paths, inner => {
                    routes.push(<Route key={inner} path={inner} render={() => this.chooseRender(inner, Component)} />);
                });
            } else {
                // A single path for a route.
                routes.push(
                    <Route
                        key={page.paths}
                        path={page.paths}
                        render={() => this.chooseRender(page.paths as string, Component)}
                    />
                );
            }
        });
        return routes;
    }

    render() {
        return (
            <div style={{ zIndex: -1 }}>
                <IntlProvider locale="en">
                    <div>
                        <ConnectedRouter history={this._history}>
                            <Switch>{this.renderPages()}</Switch>
                        </ConnectedRouter>
                    </div>
                </IntlProvider>
            </div>
        );
    }
}

export default StandardRouter;

route-object.ts

type RouteObject = {
    key: string;
    component: React.ComponentType<any>;
    paths: string | string[];
    text: string;
    shortText?: string;
    index?: number;
    pageId?: string;
    icon?: React.ReactNode;
};

export default RouteObject;

test-route.tsx

import React from 'react';

class TestRoute extends React.PureComponent {
    render() {
        return <div />;
    }
}

export default TestRoute;

同样,我不确定为什么无法将,它是PureComponent分配给ComponentType的属性。预先感谢!

下面的原始问题


我正在努力将我们的JavaScript应用程序转换为TypeScript,并且遇到了问题。我仍在尝试掌握所有TypeScript的复杂性。

我们正在运行时动态地将路由路由到redux和路由器。在使用javascript时,这可以正常工作,但是由于我已将其转换为TypeScript,因此无法对其进行编译。我收到的错误是

  

[加载器]中的错误。/src/ts/components/app/StandardRouter.tsx:63:21       TS2345:无法将类型“ ReactNode”的参数分配给类型“ ComponentType”的参数。     类型'undefined'不能分配给类型'ComponentType'。

我可以看到错误是由无效类型引起的,但是我不确定为什么。

StandardRouter.tsx

// React router component. Connects all routes to the application.
import * as React from 'react';
import { connect } from 'react-redux';
import { Route, Switch, withRouter } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import { IntlProvider } from 'react-intl';
import _forEach from 'lodash/forEach';
import _find from 'lodash/find';
import { History, createHashHistory } from 'history';
import { connectRouter } from 'connected-react-router';
import reducerRegistry from '../../api/private/core/reducer-registry';
import routeRegistry from '../../api/private/core/route-registry';
import RouteObject from '../../interfaces/route-object';
import TestRoute from '../test/test-route';

class StandardRouter extends React.Component {
    constructor(props: object) {
        super(props);
        this._history = createHashHistory();
        reducerRegistry.register({
            name: 'router',
            key: 'cb3dceb0-367b-4c2a-a0fb-a8d8671283e2',
            reducer: connectRouter(this._history)
        });
        routeRegistry.setChangeListener(() => {
            if (this._isMounted) {
                this.forceUpdate();
            } else if (!this._isMounted && !this._doUpdate) {
                this._doUpdate = true;
            }
        });
        routeRegistry.register({
            key: '90e8246f-96a6-49a5-920a-a2cf0d347fcd',
            component: <TestRoute />,
            paths: '/',
            text: 'Test 123'
        });
    }

    componentDidMount(): void {
        this._isMounted = true;
        if (this._doUpdate) {
            this.forceUpdate();
        }
    }

    private _history: History;
    private _isMounted: boolean = false;
    private _doUpdate: boolean = false;

    chooseRender(path: string, Comp: React.ComponentType): React.ReactNode {
        return <Comp />;
    }

    // Creates Route objects based on routes collection from registry
    renderPages(): React.ReactNode[] {
        const routes: React.ReactNode[] = [];
        const loadedRoutes: RouteObject[] = routeRegistry.getRoutes();
        _forEach(loadedRoutes, page => {
            const Component = withRouter(
                connect(() => ({
                    pageid: page.pageId
                }))(page.component) // <-- Error on this line, on page.component.
            );
            if (Array.isArray(page.paths)) {
                // Multiple paths available for a single route. For example "/" and "/Home" for the
                // home page.
                _forEach(page.paths, inner => {
                    routes.push(<Route key={inner} path={inner} render={() => this.chooseRender(inner, Component)} />);
                });
            } else {
                // A single path for a route.
                routes.push(
                    <Route
                        key={page.paths}
                        path={page.paths}
                        render={() => this.chooseRender(page.paths as string, Component)}
                    />
                );
            }
        });
        return routes;
    }

    render() {
        return (
            <div style={{ zIndex: -1 }}>
                <IntlProvider locale="en">
                    <div>
                        <ConnectedRouter history={this._history}>
                            <Switch>{this.renderPages()}</Switch>
                        </ConnectedRouter>
                    </div>
                </IntlProvider>
            </div>
        );
    }
}

export default StandardRouter;

route-object.ts

type RouteObject = {
    key: string;
    component: React.ReactNode;
    paths: string | string[];
    text: string;
    shortText?: string;
    index?: number;
    pageId?: string;
    icon?: React.ReactNode;
};

export default RouteObject;

test-route.tsx

import React from 'react';

class TestRoute extends React.PureComponent {
    render() {
        return <div />;
    }
}

export default TestRoute;

是否有任何东西会导致这种情况?我不确定为什么不使用ReactNode。

0 个答案:

没有答案