React Router - 更新版本后withRouter上的Typescript错误

时间:2018-01-12 04:11:22

标签: reactjs typescript react-router

我只是尝试将我的React应用升级到

react-router - 4.0.19 to 4.0.20

反应 - 16.0.30至16.0.34

typescript- version“2.7.0-insiders.20180108”

在我的应用程序中,无论我在哪里使用'withRouter',我现在都会收到神秘的Typescript错误。我甚至用'any'替换了所有界面道具,试图让它起作用。

import * as React from 'react';
import { Switch, Route, withRouter} from 'react-router-dom';
import { Login } from './Login';
import { connect } from 'react-redux';
import { RootAction, RootState } from './_redux';

class MainForm extends React.Component<any> {

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

  render() {

    return (
      <Switch>
        <Route exact={true} path="/" component={Login}/>
        <Route  path="/accounts" component={AccountsView}/>
      </Switch> 
    );
  }
}

const mapStateToProps = (state: RootState) => ({
  state
});

export const Main = withRouter(connect(mapStateToProps)(MainForm);
  

错误TS2345:类型'ComponentClass&gt;的参数&安培; {   WrappedComponent:ComponentType; }'不可分配给   'ComponentType&gt;'类型的参数。类型   “ComponentClass&GT; &安培; {WrappedComponent:   COMPONENTTYPE; }'不能分配给类型   'StatelessComponent&GT;'。       输入'ComponentClass&gt; &安培; {WrappedComponent:ComponentType; }'不提供签名匹配'(道具:   RouteComponentProps&amp; {children?:ReactNode; ,上下文?:任何):   ReactElement |空”。

如果我将最后一行转换为:

export const Main = connect(mapStateToProps)(MainForm);

我没有错误。在这里非常沮丧。 感谢

编辑,我改为

export const Main = connect(mapStateToProps)(withRouter(MainForm));
像Mayank Shukla建议的那样。但现在得到错误:

  

错误TS2345:类型'ComponentClass&gt;'的参数是   不能分配给'ComponentType&lt; {state:RootState;   }&amp; DispatchProp&GT;”。输入'ComponentClass&gt;'是   不能分配给'StatelessComponent&lt; {state:RootState; }&amp;   DispatchProp&GT;”。       输入'ComponentClass&gt;'不提供签名匹配'(props:{state:RootState;}&amp; DispatchProp&amp; {   孩子?:ReactNode; },context?:any):ReactElement |空”。

10 个答案:

答案 0 :(得分:33)

我刚刚升级到TypeScript 2.6并遇到了同样的问题。

我设法使用RouteComponentProps解决了这个问题。

对于网址http://localhost:8080/your-component/abc和路线

<Route component={YourComponent} path="/your-component/:param1?" />

组件应如下所示:

import * as React from 'react'
import { withRouter } from 'react-router-dom';
import {RouteComponentProps} from "react-router";

// Type whatever you expect in 'this.props.match.params.*'
type PathParamsType = {
    param1: string,
}

// Your component own properties
type PropsType = RouteComponentProps<PathParamsType> & {
    someString: string,
}

class YourComponent extends React.Component<PropsType> {
    render() {

        console.log(this.props); // Prints all props including routing-related
        console.log(this.props.match.params.param1); // Prints 'abc'
        console.log(typeof this.props.match.params.param1 === 'string'); // prints 'true'

        return <div>...</div>;
    }
}

export default withRouter(YourComponent);

答案 1 :(得分:12)

我必须这样解决:

import * as React from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';

interface IProps extends RouteComponentProps<any> {
  title: string;
}

class MyComp extends React.Component<IProps> {
    public render(){
        return (
           <h1>{this.props.title}</h1>
        )
    }
}

export default withRouter<IProps>(MyComp);

答案 2 :(得分:2)

这是我通常构造输入的React组件的方式:

// These props are provided when creating the component
interface OwnProps {
    // ...
}

// These props are provided via connecting the component to the store
interface StateProps {
    // ...
}

// These props are provided by the router
interface PathProps {
    // ...
}

class Component extends React.Component<OwnProps & StateProps & RouteComponentProps<PathProps>> {
    // ...
}

const mapStateToProps = (state: State, props: OwnProps): StateProps => ({
    // ...
});

export default withRouter(
    connect(mapStateToProps)(Component)
);

答案 3 :(得分:1)

使用装饰器的另一种解决方案

import { withRouter, RouteComponentProps } from "react-router";

// inform we match url /:id
interface IMatchParams {
    id: string;
}

// Note we use Partial<RouteComponentProps> to make all RouteComponentProps as optional for high order component
interface IComponentProps extends Partial<RouteComponentProps<IMatchParams>> {
    myPersonalProp: string;
}

@withRouter
export default class MyClass extends React.Component<IComponentProps>{

    public componentDidMount(){
        console.log(this.props.match.params.id);
    }
}

答案 4 :(得分:0)

类型脚本应用程序的工作语法变体是:

    import * as React from 'react';
    import { connect } from 'react-redux';
    import { withRouter } from 'react-router-dom';

    class MyComponentName extends React.Component<any, any> {
        constructor(props: any) {
            super(props);
        }
    }

    export default withRouter(
    connect(
        mapStateToProps
      )(MyComponentName) as any
    );

答案 5 :(得分:0)

这是我使用的功能性反应方法

import { RouteComponentProps } from "react-router";

interface Props extends RouteComponentProps {
    thing: Thing | false;
    onAction?: () => void;
}

export default withRouter(({ thing, onAction, history }: Props) => {

答案 6 :(得分:0)

我在TypeScript 3.6的一个非常相似/相同的问题中苦苦挣扎,无法在线找到解决方案,因此在这里我将分享自己的解决方案。我希望它可以帮助使用更复杂的应用程序的人。

javax.sound.sampled

一些注意事项:

  • 重要的部分是接口,RouteComponentProps,Props类型,React组件类型以及使用Router(...)的导出默认值。 mapStateToProps和mapDispatchToProps只是示例。
  • IAppState定义我的应用程序的redux存储的类型。如果没有的话。
  • 我在这里使用不可变的redux存储(这就是为什么“ state.getIn ...”)。

答案 7 :(得分:0)

我遇到了这个问题,最接近我的问题的答案是这个线程。但是,我不得不将建议略微更改为以下内容。分享以防万一...


import { RouteComponentProps, withRouter } from 'react-router';
import * as React from 'react';

export interface MyComponentProps extends RouteComponentProps<any> {
  propA: String;
  propB: Number;
}

function MyComponent(props: MyComponentProps) {
   return (
     <div>
        <div>{props.propA} - {props.propB}</div>
        <button onClick={() => props.history.push('/some-other-page')}>Go</button>
     </div>
   )
}

export default withRouter(MyComponent);


答案 8 :(得分:0)

为了仍然允许在您的组件上使用自定义参数,您必须将 props 接口提供给 withRouter

此外,withRouter 要求您指定正在使用的组件类型(即 FunctionComponent / Component)。

另请注意,withRouter 将与道具一起提供 staticContext。这应该从集合中删除。在将它们传递给被包装的组件之前,请使用 props,否则,您将收到此错误(除非您专门将组件接口为接受 staticContext)。

index.js:1 Warning: React does not recognize the 'staticContext' prop on a DOM element...

对于函数组件,以下是如何正确键入 withRouter 包装器的示例:

对于类组件,以下是如何正确键入 withRouter 包装器的示例。

import React, { FunctionComponent } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';

interface MyCompProps extends RouteComponentProps<any> {
  title: string;
}

const MyComp: FunctionComponent<MyCompProps> = ({ title }) => (
    <h1>{ title }</h1>
);

export default withRouter<MyCompProps, Component<MyCompProps>>(({ staticContext, ...props }) => MyComp(props));

对于类组件,以下是如何正确键入 withRouter 包装器的示例。

import React, { Component } from 'react';
import { RouteComponentProps, withRouter } from 'react-router-dom';

interface MyCompProps extends RouteComponentProps<any> {
  title: string;
}

class MyComp extends Component<MyCompProps> {
    public render(){
        return (
           <h1>{this.props.title}</h1>
        )
    }
}

export default withRouter<MyCompProps, Component<MyCompProps>>(({ staticContext, ...props }) => MyComp(props));

答案 9 :(得分:-1)

如果键入“any”有问题,您可以使用这样的技巧。它对我有用。

import { withRouter, RouteComponentProps } from 'react-router-dom';

type ComponentProps = RouteComponentProps;

const Component: React.FC = () => {
   return <div>This is component</div>
}

export default withRouter(Component)