Help us understand the problem. What is going on with this article?

サルでもわかったreact-router v5【サンプルの読解と実践】

5分と5秒かけて作成・デプロイしたTypescript + React + Firebase アプリに 、URLで表示を分ける機能:ルーティング機能を付け加えていきます。

アプリのディレクトリ構成はこんな感じ。基本的にはcreate-react-app直後と変わりません。

.
|-- README.md
|-- build # 以下略
|-- firebase.json
|-- node_modules # 以下略
|-- package.json
|-- public # 以下略
|-- src
|   |-- App.css
|   |-- App.test.tsx
|   |-- App.tsx
|   |-- index.css
|   |-- index.tsx
|   |-- logo.svg
|   |-- react-app-env.d.ts
|   `-- serviceWorker.ts
|-- tsconfig.json
`-- yarn.lock

React Router DOM の導入

yarn add react-router-dom
yarn add @types/react-router-dom # typescriptプロジェクトではこちらも必要

これでreact-router-dom(v5.0.1) がインストールされました!

サンプルを読む

まず、サンプルを読んで使い方を勉強していきます。

基本的な使用例

クイックスタート : 基本的なルーティングのコードをそのままsrc/App.jsに張り付けて動作させると・・・

router.gif
お、URLで表示が変わっていますね!

なるほど、コンポーネントを定義して

function Index() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function Users() {
  return <h2>Users</h2>;
}

URLとコンポーネントを紐づけて

        <Route path="/" exact component={Index} />
        <Route path="/about/" component={About} />
        <Route path="/users/" component={Users} />

任意の要素にLINKの役割を持たせるって感じか

            <li>
              <Link to="/about/">About</Link>
            </li>

こちらはかなり直感的に使うことができそうです。

応用的な使用例

クイックスタート : ネストされたルーティングのコードをそのままsrc/App.jsに張り付けて動作させると・・・

router-extends.gif

なるほど、/topics/components/topics/props-v-stateのような場合ですね。

コードはどうなるのか見ていきましょう。

/topicsに入るとまずはTopicsコンポーネントにルーティングされるようです

function App() {
  return (
    <Router>
      <div>
        <Header />

        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/topics" component={Topics} />
      </div>
    </Router>
  );
}

Topics にルーティングされた場合に、引数 match が流れ込んできて、

match.url で URLを引き継ぐ(ネストさせる)ことができるように見えます。

function Topics({match}:Props) {
  return (
    <div>
      <h2>Topics</h2>

      <ul>
        <li>
          <Link to={`${match.url}/components`}>Components</Link>
        </li>
        <li>
          <Link to={`${match.url}/props-v-state`}>Props v. State</Link>
        </li>
      </ul>

idという名前の引数で/topics以下にネスとしてきた文字列を受け取って、Topicコンポーネントに紐づけているように見えます。

ネストしなかった場合はPlease select a topic.h3で表示させる処理も書かれていますね。

      <Route path={`${match.path}/:id`} component={Topic} />
      <Route
        exact
        path={match.path}
        render={() => <h3>Please select a topic.</h3>}
      />
    </div>
  );
}

Topicコンポーネントは、Topicsと同様に引数 match をとるコンポーネントのようです。

match は、id? を引数にとるRouteComponentPropsextendsしているので、match.params.idという呼び出しができるのでしょう。

interface Props extends RouteComponentProps<{ id?: string }>{} // TypeScript対応で付け加え

function Topic({match}:Props) {
  return <h3>Requested Param: {match.params.id}</h3>;
}

こちらは読解にあまり自信がないですが、何とか使うことはできそうです。

マネしてみる

自分のアプリでもreact-router-domを使ってみます。

現在作成中のe-Sports専用のクラウドファウンディング・サービス「e-Sports-Funding(仮)」のルーティング構成はこんな感じがいいかな

  • / : トップページ
  • /create : プロジェクト作成画面
  • /search : プロジェクト検索画面
  • /project/:project_id : プロジェクト詳細画面
  • /funding/:project_id : プロジェクト出資画面
  • /mypage/ : マイページ

基本的な使用例

ネストは無いものとしてルーティング

handsOn.gif

それぞれのコンポーネントたちをsrc/components以下に定義して、App.tsxでURLとコンポーネントを紐づけるだけなので、これは簡単です。

応用的な使用例

  • トップページ・プロジェクト作成画面・プロジェクト検索画面・マイページはどこからでも行ける

  • プロジェクト詳細画面はプロジェクト検索画面から引数:project_idをとった場合に行ける

  • プロジェクト出資画面はプロジェクト詳細画面から引数:project_idをとった場合に行ける

みたいな、比較的複雑なルーティングを構成してみます。
handsOn2.gif
App.tsxにURLとコンポーネントを紐づける設定をすべて書いて、コンポーネントではリンクの設置と、引数の受け渡しのみを行うようにしました。

全員の親となるコンポーネントにルーティング設定を並べたほうが、一覧性が高くて良いかもしれませんね。

リダイレクトも試してみました。

const App: React.FC = () => {
  return (
    <Router>
      <div>
        {Header()}
        <Route exact path="/" component={Toppage}/>
        <Route path="/create" component={CreateProject}/>
        <Route path="/search" component={SearchProject}/>
        <Route path="/project/:project_id" component={ProjectDetail}/>
        <Route exact path="/project" render={()=>(<Redirect to="/search"/>)}/>
        <Route path="/funding/:project_id" component={Funding}/>
        <Route exact path="/funding" render={()=>(<Redirect to="/search"/>)}/>
        <Route path="/mypage" component={Mypage}/>
      </div>
    </Router>
  );
}

今後の展望

ルーティングができたので、次はいよいよ画面!

Material UIで見た目を整えていこうかと思います。

その次は状態変化の制御、続いてデータベースの導入になるのかな。

完成が待ち遠しいです。

参考ページ

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away