2

Taking this example route which takes a route param slug:

ROUTES.ts

export const SOME_ROUTE = `/some-route/:slug`;

And this <Switch> component that will render <Route>'s.

AllRoutes.tsx

import React from "react";
import * as ROUTES from "@routes/ROUTES";

interface AllRoutes {  
}

const AllRoutes: React.FC<AllRoutes> = (props) => {
  console.log("Rendering AllRoutes...");

  return(
    <Switch>
      <Route exact path={ROUTES.SOME_ROUTE} component={MyComponent}/>
    </Switch>
  );
};

export default AllRoutes;

And now from the rendered component:

MyComponent.tsx

import React from "react";
import HomePage from "./HomePage";
import { RouteComponentProps } from "react-router-dom";

interface MyComponent extends RouteComponentProps {
}

const MyComponent: React.FC<MyComponent> = (props) => {
  console.log("Rendering MyComponent...");

  console.log(props.match.params.slug);  // TRYING TO ACCESS THE `:slug` ROUTE PARAM

  return(
    <HomePage/>
  );
};

export default MyComponent;

QUESTION

I get an error saying that the slug property does not exist. Even though it 100% exists, 'cause the value gets logged. But Typescript is unaware of it.

Do I need to manually extend the RouteComponentProps to add that props.match.params.slug property?

enter image description here

The routeProps (history, match, location) are present as you can see from the picture below.

enter image description here

cbdeveloper
  • 14,014
  • 11
  • 57
  • 145
  • 2
    Why don't you supply the expected parameters? Like `RouteComponentProps`, presumably. Dupe of https://stackoverflow.com/q/50047977/3001761. – jonrsharpe Aug 28 '20 at 14:46
  • Thanks for your reply. Something like this: `interface MyComponent extends RouteComponentProps}` ? Won't I be overwriting other stuff by doing this? – cbdeveloper Aug 28 '20 at 14:47
  • Overwriting *what* other stuff? `MyComponent` doesn't define anything else, it seems pointless; just use `React.FC>`. – jonrsharpe Aug 28 '20 at 14:49
  • @jonrsharpe I mean other stuff defined in `RouteComponentProps`, that comes from `@types/react-router-dom`. – cbdeveloper Aug 28 '20 at 14:51
  • What other stuff? What do you think the generic is for if *not* specifying the parameters? Look at the definition: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/a047ceb2643f2defd7f7a35aa13c6d00b49de154/types/react-router/index.d.ts#L69-L78. – jonrsharpe Aug 28 '20 at 14:54
  • @jonrsharpe still on a learning curve here.. but my concern is that the property I want to add is nested on `match > params > slug`. – cbdeveloper Aug 28 '20 at 14:56
  • And `match.params` is exactly what the first generic type is used for. Please read the dupe and try it out; worst comes to worst, you can undo the change. – jonrsharpe Aug 28 '20 at 14:57
  • But there are other properties under `match`. Like `isExact`, `params`, `path` and `url`. how can I extend `params` only? – cbdeveloper Aug 28 '20 at 15:00
  • ...so what? The first generic type argument only gets applied to `match.params`. If you don't believe me, or anyone on that dupe, and can't just try it out for some reason, look at the definitions I linked to, see where that generic parameter gets applied; see https://www.typescriptlang.org/docs/handbook/generics.html if you're unfamiliar with generic types. – jonrsharpe Aug 28 '20 at 15:01
  • You are right, it works. I was testing since you've first mentioned, but I forgot that I trying it on by using the `useParams` hook. Which is a different situation. Thanks a lot for your help. Feel free to write an answer and I'll accept it. – cbdeveloper Aug 28 '20 at 15:05
  • I'd suggest just deleting the question; it's answered on the dupe and that was easy enough to find. – jonrsharpe Aug 28 '20 at 15:06
  • Does this answer your question? [In ReactJS trying to get params but I get property 'id' does not exist on type '{}'](https://stackoverflow.com/questions/50047977/in-reactjs-trying-to-get-params-but-i-get-property-id-does-not-exist-on-type) – Aaron Frary Apr 15 '21 at 21:31

1 Answers1

2

With the help of the comments and these other contents:

Here is how I'm doing it:

import React from "react";
import HomePage from "./HomePage";
import { RouteComponentProps } from "react-router-dom";

interface RouteParams {
  slug: string
}

interface MyComponent extends RouteComponentProps<RouteParams> {
}

const MyComponent: React.FC<MyComponent> = (props) => {
  console.log("Rendering MyComponent...");

  console.log(props.match.params.slug);

  return(
    <HomePage/>
  );
};

export default MyComponent;

useParams()

And also using the useParams() hook:

interface RouteParams {
  slug: string
}

const params = useParams<RouteParams>();
cbdeveloper
  • 14,014
  • 11
  • 57
  • 145