Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router - Typescript errors on withRouter after updating version

I just tried to upgrade my React app to

react-router - 4.0.19 to 4.0.20

react- 16.0.30 to 16.0.34

typescript- version "2.7.0-insiders.20180108"

In my app, wherever I am using 'withRouter', I now get cryptic Typescript errors. I even replaced all interface props with 'any' just to try to make it work.

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

error TS2345: Argument of type 'ComponentClass> & { WrappedComponent: ComponentType; }' is not assignable to parameter of type 'ComponentType>'. Type 'ComponentClass> & { WrappedComponent: ComponentType; }' is not assignable to type 'StatelessComponent>'. Type 'ComponentClass> & { WrappedComponent: ComponentType; }' provides no match for the signature '(props: RouteComponentProps & { children?: ReactNode; }, context?: any): ReactElement | null'.

If i convert the last line to this :

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

I don't get errors. seriously frustrated here. Thanks

EDIT, I changed to

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

like suggested by Mayank Shukla. but now get the error:

error TS2345: Argument of type 'ComponentClass>' is not assignable to parameter of type 'ComponentType<{ state: RootState; } & DispatchProp>'. Type 'ComponentClass>' is not assignable to type 'StatelessComponent<{ state: RootState; } & DispatchProp>'. Type 'ComponentClass>' provides no match for the signature '(props: { state: RootState; } & DispatchProp & { children?: ReactNode; }, context?: any): ReactElement | null'.

like image 778
29er Avatar asked Jan 12 '18 04:01

29er


People also ask

Why withRouter is not working?

The error "export 'withRouter' (imported as 'withRouter') was not found in 'react-router-dom'" occurs because the withRouter function has been removed in react router v6. To solve the error, install version 5.2. 0 of react router by running npm install [email protected] .

Is withRouter deprecated?

The library-provided HOC, withRouter, has been deprecated in React Router v6. If you need to use v6 and are using class-based React components, then you will need to write your own HOC which wraps the v6 use* hooks.

What is RouteComponentProps?

RouteComponentProps looks to be a Typescript interface definition of react-router-dom's route-props. The RouteComponentProps prop-types definition may've been part of react-router-dom but isn't currently exported. I found the Typescript export in Definitely Typed.

How do you use withRouter in react?

React Router has an higher-order component called withRouter with which we can pass in the React Router's history, location, and match objects to our React components as props. To use withRouter , you should wrap your App component inside withRouter() as a parameter.


2 Answers

I just upgraded to TypeScript 2.6 and got same issue.

I managed to resolve it by using RouteComponentProps.

For URL http://localhost:8080/your-component/abc and route

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

Component should look like this:

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); 
like image 52
Pavel Avatar answered Oct 14 '22 12:10

Pavel


I have to solve it like this:

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); 
like image 44
jakobdo Avatar answered Oct 14 '22 14:10

jakobdo