Search code examples
reactjstypescriptreact-router-v4browser-history

react-router v4's Route doesn't pass it's props to component - in React Typescript


I just started to use React Router v4 and can't manage to use the history of Browserrouter. For example, when I try to access this.props.history.push("/")I got the error:

TS2339: Property 'history' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'

I'm using React Router v4 with Browserrouter and React with Typescript. It seems that the three props (location, history, match) from React Router's Route are not passed to it's component. Am I doing anything wrong with Typescript or with React Router?

index.tsx

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import {
    BrowserRouter as Router, Route
} from 'react-router-dom';
import Login from "./Login";
import Questionnaire from "./Questionnaire";
import Registration from "./Registration";
import NotFound from "./NotFound";
import GotNoHistory from "./GotNoHistory";
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
    <Router>
        <Route exact={true} path="/" component={Questionnaire}/>
        <Route path="/login" component={Login}/>
        <Route path="/registration" component={Registration}/>
        <Route path="/gotNoHistory" component={GotNoHistory} />
        <Route component={NotFound}/>
    </Router>,
    document.getElementById('reactApp')
);

registerServiceWorker();

example component GotNoHistory.tsx

import * as React from 'react';
import './index.css';

class GotNoHistory extends React.Component {

    render() {
        return <div>{this.props.history.push("/")}</div>;
    }
}

export default GotNoHistory;

Update

I've discovered RouteComponentProps. I added this props to my class GotNoHistory and the error was gone. Is that the correct way to solve the problem?

import {RouteComponentProps} from 'react-router';
class GotNoHistory extends React.Component<RouteComponentProps<any>, any> {
    render() {
        return <div>Go back {this.props.history.push("/")}</div>;
    }
}

Update for Chris solution

import * as React from 'react';
import './index.css';
import {Route} from "react-router-dom";

interface Props {
}

interface State {
}

export default class GotNoHistory extends React.Component<Props & Route, State> {
    render() {
        return this.props.history.push("/");
    }
}

Results in nearly the same error: TS2339: Property 'history' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{Props & Route<RouteProps>}>'


Solution

  • Solved by myself.

    My solution was to add the route props to the types of my props.

    import {RouteComponentProps} from 'react-router';
    class GotNoHistory extends React.Component<RouteComponentProps<any>> {
        render() {
            return <div>Go back {this.props.history.push("/")}</div>;
        }
    }
    

    For those who don't know, like me before, what this means <RouteComponentProps<any>>:

    The parameter ist the prop type. So before it was only React.Component which means that we don't expect any props from my router. So this couldn't work out!