What TypeScript type should I use to reference the match object in my props?

73,072

Solution 1

You don't need to add it explicitly. You can use RouteComponentProps<P> from @types/react-router as a base interface of your props instead. P is type of your match params.

import { RouteComponentProps } from 'react-router';

// example route
<Route path="/products/:name" component={ProductContainer} />

interface MatchParams {
    name: string;
}

interface Props extends RouteComponentProps<MatchParams> {
}
// from typings
import * as H from "history";

export interface RouteComponentProps<P> {
  match: match<P>;
  location: H.Location;
  history: H.History;
  staticContext?: any;
}

export interface match<P> {
  params: P;
  isExact: boolean;
  path: string;
  url: string;
}

Solution 2

To add onto @Nazar554's answer above, the RouteComponentProps type should be imported from react-router-dom, and implemented as follows.

import {BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom';

interface MatchParams {
    name: string;
}

interface MatchProps extends RouteComponentProps<MatchParams> {
}

Further, to allow for re-usable components, the render() function allows you to pass only what the component needs, rather than the entire RouteComponentProps.

<Route path="/products/:name" render={( {match}: MatchProps) => (
    <ProductContainer name={match.params.name} /> )} />

// Now Product container takes a `string`, rather than a `MatchProps`
// This allows us to use ProductContainer elsewhere, in a non-router setting!
const ProductContainer = ( {name}: string ) => {
     return (<h1>Product Container Named: {name}</h1>)
}

Solution 3

Simple solution

import { RouteComponentProps } from "react-router-dom";

const Container = ({ match }: RouteComponentProps<{ showId?: string}>) => {
 const { showId } = match.params?.showId;//in case you need to take params
}

Solution 4

The problem was that even after creating an interface for the match<Params> the type warning was still there. Here is the code which worked for me:

interface MatchParams {
    firstParam: string;
    optionalParam?: string;
}

export const CreditPortfolioDetail: FC<RouteComponentProps<MatchParams>> = (props) => {
    const { firstParam, optionalParam} = props.match.params; 
    // ...
}
Share:
73,072

Related videos on Youtube

Nicolas Blanco
Author by

Nicolas Blanco

Ruby on Rails developer and web enthusiast. Go to my Github account https://github.com/nicolasblanco to see some of my open source work... I've contributed to many popular open source Ruby/Rails projects (Devise, Bundler, Mongoid, Authlogic, ThinkingSphinx, etc.)

Updated on September 26, 2021

Comments

  • Nicolas Blanco
    Nicolas Blanco over 2 years

    In my React containers/component, which type could I use to reference the match part included by React Router DOM?

    interface Props {
      match: any // <= What could I use here instead of any?
    }
    
    export class ProductContainer extends React.Component<Props> {
      // ...
    }
    
  • Glstunna
    Glstunna over 4 years
    The problem with this is that Typescript then expects every use of that component to be actually passed in location history props etc. RouteComponentProps should have those props as optional. Have to wrap with Partial.
  • Rey Wang
    Rey Wang over 4 years
    Awesome! nice supplement
  • Toskan
    Toskan about 4 years
    @Glstunna thanks for making me aware, how would that look like with partial? As well OP: please include your imports.
  • Leonardo Viada
    Leonardo Viada about 3 years
    TypeScript keeps asking me to pass the whole props set down to the component (`<MyComp history={...} location={...} .../>, I have the same code as seen above.
  • Nazar554
    Nazar554 about 3 years
    @LeonardoViada Try passing the component using <Route component={MyComp} />
  • chrisl08
    chrisl08 almost 3 years
    What is FC ? FC<RouteComponentProps<MatchParams>>
  • Mike Mansell
    Mike Mansell almost 3 years
    It's React.FC, which is a type alias for React.FunctionComponent. Your function is actually a FunctionComponent, and by explicitly stating that, you also get the children property automatically added to your props (similar to how RouteComponentProps automatically adds location, match, etc.)