LoginSignup
119
75

More than 5 years have passed since last update.

React Router with TypeScriptでちゃんと型をつける

Posted at

react-routerでRouteコンポーネントを使って<Route path='foo' component={Bar}/>のように書くと、Barコンポーネントにはmatch,location,historyの3つのpropsが渡されます。

これらのpropsをどう型定義するかという話です。

Routing

例えば以下のようなroutingがあるとします。

app.tsx
  <BrowserRouter>
    <Switch>
      <Route path="/counter" component={Counter} />
    </Switch>
  </BrowserRouter>

Counterコンポーネントにはmatch, location, historyのpropsが渡されます。

RouteComponentProps

Routeのcomponentに指定したコンポーネントのpropsはreact-router-domのRouteComponentPropsをextendする形で使えばうまく型定義できます。

counter.tsx
import { RouteComponentProps } from 'react-router-dom'

interface Props extends RouteComponentProps<{}> {
 // 他の型定義
}

const Counter = (props: Props) => (
  <div>
    <Navi history={props.history} />
  </div>
)

RouteComponentPropsの型定義:

index.d.ts
import * as React from 'react';
import * as H from 'history';

export interface RouteComponentProps<Params extends { [K in keyof Params]?: string } = {}, C extends StaticContext = StaticContext, S = H.LocationState> {
  history: H.History;
  location: H.Location<S>;
  match: match<Params> | null;
  staticContext?: C;
}

paramsが必要なときはRouteComponentProps<{id: string}>という感じで渡してあげれば良いです。

History

さらにCounterがNaviという子コンポーネントを持っており、historyだけ渡している場合にNaviではどう型を定義するかというと、RouteComponentProps型定義でも使われているhistoryを使えば良いです。

navi.tsx

import * as H from 'history'
interface Props {
  history: H.History
}

const Navi = (props: Props) => (<div><button onClick={props.history.push('/next')}/><div/>)

locationの場合は、H.LocationでOK。

以上です。

119
75
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
119
75