wake-up-neo.com

reakt-Router-Dom mit TypeScript

Ich versuche Reaktiver Router mit TypeScript zu verwenden. Ich habe jedoch einige Probleme bei der Verwendung der withRouter-Funktion. In der letzten Zeile bekomme ich einen ziemlich seltsamen Fehler:

Argument of type 'ComponentClass<{}>' is not assignable to parameter of type 'StatelessComponent<RouteComponentProps<any>> | ComponentClass<RouteComponentProps<any>>'.
  Type 'ComponentClass<{}>' is not assignable to type 'ComponentClass<RouteComponentProps<any>>'.
    Type '{}' is not assignable to type 'RouteComponentProps<any>'.
      Property 'match' is missing in type '{}’

Code sieht so aus:

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

interface HomeProps extends RouteComponentProps<any> {
}

interface HomeState { }

class Home extends React.Component<HomeProps, HomeState> {
  constructor(props: HomeProps) {
    super(props);
  }
  public render(): JSX.Element {
    return (<span>Home</span>);
  }
}

const connectModule = connect(
  (state) => ({
    // Map state to props
  }),
  {
    // Map dispatch to props
  })(Home);

export default withRouter(connectModule);
34
Haris Bašić

Ich verwende einen anderen Ansatz, um dies zu beheben. Ich trenne immer die verschiedenen Eigenschaften (Router, Normal und Versand), daher definiere ich die folgenden Schnittstellen für meine Komponente:

interface HomeRouterProps {
  title: string;   // This one is coming from the router
}

interface HomeProps extends RouteComponentProps<HomeRouterProps> {
  // Add your regular properties here
}

interface HomeDispatchProps {
  // Add your dispatcher properties here
}

Sie können jetzt entweder einen neuen Typ erstellen, der alle Eigenschaften in einem einzigen Typ zusammenfasst, aber ich kombiniere die Typen immer während der Komponentendefinition (ich füge den Status hier nicht hinzu, aber wenn Sie einen benötigen, machen Sie einfach weiter). Die Komponentendefinition sieht folgendermaßen aus:

class Home extends React.Component<HomeProps & HomeDispatchProps> {
  constructor(props: HomeProps & HomeDispatchProps) {
    super(props);
  }

  public render() {
    return (<span>{this.props.match.params.title}</span>);
  }
}

Nun müssen wir die Komponente über einen Container mit dem Zustand verbinden. Es sieht aus wie das:

function mapStateToProps(state, ownProps: HomeProps): HomeProps => {
  // Map state to props (add the properties after the spread)
  return { ...ownProps };
}

function mapDispatchToProps(dispatch): HomeDispatchProps {
  // Map dispatch to props
  return {};
}

export default connect(mapStateToProps, mapDispatchToProps)(Hello);

Diese Methode ermöglicht eine vollständig typisierte Verbindung, sodass die Komponente und der Container vollständig typisiert sind und eine Umgestaltung sicher ist. Das einzige, was für das Refactoring nicht sicher ist, ist der Parameter in der Route, der der HomeRouterProps-Schnittstelle zugeordnet ist.

30
Ramon de Klein

Ich denke, es ist ein TypeScript-Kompilierungsproblem, aber ich habe eine Problemumgehung gefunden:

interface HomeProps extends RouteComponentProps<any>, React.Props<any> {
}
14
carlosvin

Dies ist ein TypeScript-Problem. Da withRouter () die Routing-Requisiten bereitstellt, die Sie zur Laufzeit benötigen, möchten Sie den Verbrauchern mitteilen, dass sie nur die other - Requisiten angeben müssen. In diesem Fall können Sie einfach eine einfache ComponentClass verwenden:

export default withRouter(connectModule) as React.ComponentClass<{}>;

Wenn Sie andere Requisiten (definiert in einer Schnittstelle namens OwnProps) hätten, die Sie übergeben möchten, können Sie Folgendes tun:

export default withRouter(connectModule) as React.ComponentClass<OwnProps>;

Es gibt etwas mehr Diskussion hier

6

Es sieht so aus, als hätten Sie die richtige Verwendung, um die Übereinstimmung, den Verlauf und die Standortstützen auf Ihre Komponente anzuwenden. Ich würde in Ihrem node_modules-Verzeichnis nachsehen, welche Versionen von react-router und react-router-dom Sie haben, sowie die @types-Module.

Ich habe im Wesentlichen den gleichen Code wie Sie und meiner arbeitet mit den folgenden Versionen:

{
  "@types/react-router-dom": "^4.0.4",
  "react-router-dom": "^4.1.1",
}
2
Peter Benavides

So mache ich das:

interface IOwnProps {
  style?: CSSProperties;
}

interface INavProps {
  item?: string;
}

type IProps = IOwnProps & RouteComponentProps<INavProps>;

export default class MapScreen extends PureComponent<IProps> {
  ...
}
1
Jaroslav

Nachdem ich die TypeScript-Definitionen durchsucht hatte, entdeckte ich die RouteComponentProps-Schnittstelle, sodass ich jetzt meine Container so modelliere 

type RouteParams = {
    teamId: string; // must be type string since route params
}

interface Props extends RouteComponentProps<RouteParams>, React.Props<RouteParams> { }

type State = {
    players: Array<Player>;
}

export class PlayersContainer extends React.Component<Props, State>{} 

in der Komponentenklasse kann nun auf die Routenrequisiten wie folgt zugegriffen werden: let teamid = this.props.match.params.teamId; 

0
SimperT

+1 für Ramons Antwort. Sie können hier absolut die vollständige Typenüberdeckung erhalten. Um etwas hinzuzufügen - ich habe den Aufruf von withRouter hinzugefügt.

interface FooProps extends RouteComponentProps<Foo> {
  foo: string;
}

const Foo = ({ history, foo }: FooProps) => <span/>;

const RoutedFoo = withRouter(Foo);

meine Abhängigkeiten:

"@types/react-router-dom": "^4.3.0",
"TypeScript": "^2.9.2",
0
dmwong2268