web-dev-qa-db-ja.com

Reactルーター-バージョン更新後のwithRouterでのTypeScriptエラー

Reactアプリを

react-router-4.0.19から4.0.20

反応-16.0.30から16.0.34

TypeScript-バージョン "2.7.0-insiders.20180108"

私のアプリでは、「withRouter」をどこで使用しても、不可解なTypeScriptエラーが発生します。私はそれを機能させるためだけにすべてのインターフェースの小道具を「任意」に置き換えました。

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>&{WrappedComponent:ComponentType;の引数} 'はタイプ' ComponentType> 'のパラメーターに割り当てることができません。タイプ 'ComponentClass>&{WrappedComponent:ComponentType; } 'はタイプ' StatelessComponent> 'に割り当てることができません。タイプ 'ComponentClass>&{WrappedComponent:ComponentType; } 'はシグニチャー'(props:RouteComponentProps&{children ?: ReactNode;}、context ?: any)に一致しません:ReactElement |ヌル'。

最後の行をこれに変換すると:

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

エラーは発生しません。ここでひどくイライラした。ありがとう

[〜#〜] edit [〜#〜]、私は

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

mayank Shuklaによって提案されたように。しかし今度はエラーが出ます:

エラーTS2345:タイプ 'ComponentClass>'の引数は、タイプ 'ComponentType <{のパラメーターに割り当てることができません。状態:RootState; }&DispatchProp> '。タイプ 'ComponentClass>'はタイプ 'StatelessComponent <{に割り当てることができません。状態:RootState; }&DispatchProp> '。タイプ 'ComponentClass>'はシグニチャー '(props:{state:RootState;}&DispatchProp&{children ?: ReactNode;}、context ?: any):ReactElement |に一致しませんヌル'。

35
29er

TypeScript 2.6にアップグレードしましたが、同じ問題が発生しました。

RouteComponentPropsを使用してなんとか解決しました。

URL 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);
82
Pavel

私はそれを次のように解決する必要があります:

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);
23
jakobdo

ここに私が通常入力した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)
);
5
Max

デコレーターを使用した別のソリューション

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);
    }
}
3
Daniel Krom

これが私が使用する機能的な反応アプローチです

import { RouteComponentProps } from "react-router";

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

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

タイプスクリプトアプリケーションの構文のバリアントは次のとおりです。

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

    interface ComponentProps {
    // Your properties here
    }

    interface ComponentState {
    // Your properties here
    }

    interface MapStateToPropsTypes {
    // Your properties here
    }

    interface MapDispatchToPropsTypes {
    // Your properties here
    }

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

    export default withRouter(
    connect<MapStateToPropsTypes, MapDispatchToPropsTypes>(
        mapStateToProps,
        mapDispatchToProps
      )(MyComponentName) as any
    );
1
Jackkobec

TypeScript 3.6で非常によく似た/同じ問題に悩んでいて、オンラインで解決策を見つけることができなかったので、ここで自分の解決策を共有します。より複雑なアプリで作業している人に役立つことを願っています。

import React, { memo } from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { ThunkDispatch } from 'redux-thunk';
import { connect } from 'react-redux';
import { AnyAction } from 'redux';

interface IStateProps {
  name: string;
  sessionLanguage: string;
}

interface IDispatchProps {
  handleLogout: () => void;
}

type Props = IStateProps & IDispatchProps & RouteComponentProps<any>;

const MyCoolComponent = ({
  sessionLanguage,
  handleLogout,
  history,
}: Props) => {
  return null;
};

const mapStateToProps = (state: IAppState): IStateProps => ({
  name: state.getIn(['session', 'name']),
  sessionLanguage: state.getIn(['session', 'language']),
});

const mapDispatchToProps = (
  dispatch: ThunkDispatch<{}, {}, AnyAction>
): IDispatchProps => ({
  handleLogout: async () => {
    await dispatch(logout());
  },
});

export default withRouter(
  connect<IStateProps, IDispatchProps, {}, IAppState>(
    mapStateToProps,
    mapDispatchToProps
  )(memo(NavigationLayout))
);

いくつかのメモ:

  • 重要な部分は、インターフェース、RouteComponentProps、タイプProps、Reactコンポーネントタイプ、およびエクスポートのデフォルトwithRouter(...)です。mapStateToPropsおよびmapDispatchToPropsは単なる例です。
  • IAppStateは、アプリのreduxストアのタイプを定義します。持っていない場合。
  • ここでは不変のreduxストアを使用しています(そのため、 "state.getIn ..."を使用しています)。
0
Raunhofer