【React】react-tabsでのルーティングの設定方法

【React】react-tabsでのルーティングの設定方法

どうも、イソップです。

昨日紹介したreact-tabsですが、タブ切り替えと同時にURLも変更したいことがあると思います。

【昨日の記事】【React】react-tabsが一番シンプルで使いやすい

今日は、react-tabsを使ったルーティング設定について紹介します。

ルーティング設定を追加

今回の目標は、/page で表示されるページ内にタブ切り替えがあり、
そのタブを切り替えると、/page/page/tab2/page/tab3 とURLが変更されます。

ではまずはルーティングを追加します。

<Route path="/" component={App}>
  <Route path="page" component={Page}>
    <Route path=":tab" />
  </Route>
</Route>

react-routerの v3.x を例にしています。
<Route path=":tab" /> がタブ用のURL設定です。

次に、昨日の記事で紹介した react-tabsのコンポーネントを Page コンポーネントに配置します。

import React, { Component } from 'react';
import { render } from 'react-dom';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';

class Page extends Component {

  handleSelect(index, last) {
    console.log('Selected tab: ' + index + ', Last tab: ' + last);
  }

  render() {
    return (

      <Tabs
        onSelect={this.handleSelect}
        selectedIndex={2}
      >

        <TabList>
          <Tab>tab1</Tab>
          <Tab>tab2</Tab>
          <Tab>tab3</Tab>
        </TabList>

        <TabPanel>
          <h2>Hello from tab1</h2>
        </TabPanel>
        <TabPanel>
          <h2>Hello from tab2</h2>
        </TabPanel>
        <TabPanel>
          <h2>Hello from tab3</h2>
        </TabPanel>

      </Tabs>
    );
  }
}

この Page コンポーネントを編集していきます。

タブの初期化と切り替え時の処理

タブを切り替えた際のURLリストを保持しておく必要があります。
今回は Page コンポーネントに持たせます。

class Page extends Component {
  constructor(props) {
    super(props);

    this.tabs = [ '', 'tab2', 'tab3' ];

  }

  ...

}

constructor の中で、this.tabs を定義します。

先ほどrouteで定義した path=":tab"が、コンポーネントの props.params.tabで取得できます。
例えば、URLが /page/tab2 でアクセスすると、props.params.tab には tab2 がセットされます。

このパスキーワードと、this.tabs で定義したキーワードがマッチしたら、選択したタブに対応するパネルを表示します。
マッチしなかったら、例外処理用のビューコンポーネントを表示しておくと良いでしょう。

では初期化とタブ選択時の処理を追加します。

class Page extends Component {
  constructor(props) {
    super(props);

    this.tabs = [ '', 'tab2', 'tab3' ];

    this.handleSelect = this.handleSelect.bind(this); // メソッド内のthisをPageに
  }

  // indexを取得するメソッドを定義
  getTabIndex(tab = this.props.params.tab || '') {
    return this.tabs.indexOf(tab);
  }

  // タブ選択時のコールバック
  handleSelect(index, last) {
    // indexは最後の "/" を付けない
    const tabPath = this.tabs[index] ? '/' + this.tabs[index] : '';
    // URLを変更する
    this.props.router.push('/page' + tabPath);
  }

  render() {

    // this.tabsに一致しない場合はNoTabを表示する
    if (this.getTabIndex() < 0) return <NoTab />;

    return (

        <Tabs
          onSelect={this.handleSelect}
          selectedIndex={this.getCategoryIndex()}
        >

        ...

    );
  }
}

上から順番に、説明していきます。

初期化処理の解説

  // indexを取得するメソッドを定義
  getTabIndex(tab = this.props.params.tab || '') {
    return this.tabs.indexOf(tab);
  }

getTabIndex メソッドは、URLの :tab キーワードから、this.tabs にマッチするインデックス(順番)を取得します。
これは、タブの初期表示インデックスに利用します。

        <Tabs
          onSelect={this.handleSelect}
          selectedIndex={this.getCategoryIndex()}
        >

キーワードにマッチしなければ、-1 が返ります。つまり、表示するタブがないことになります。

  render() {

    // this.tabsに一致しない場合はNoTabを表示する
    if (this.getTabIndex() < 0) return <NoTab />;

    ...

例では、<NoTab /> コンポーネントを表示しています。中身に「ページは存在しません」としておくと良いです。

タブ選択処理の解説

  // タブ選択時のコールバック
  handleSelect(index, last) {
    // indexは最後の "/" を付けない
    const tabPath = this.tabs[index] ? '/' + this.tabs[index] : '';
    // URLを変更する
    this.props.router.push('/page' + tabPath);
  }

そして、タブ選択時の handleSelect メソッドでは、選択したタブのURLを整形し、
react-routerの機能でURLを変更します。

初期表示URLは、/page にしたいので、キーワードが何もなければそのままに、キーワードがあれば頭に / を付けています。

これで実装完了です。

五十川 洋平(Yohei Isokawa)

五十川 洋平(Yohei Isokawa)

フロントエンドエンジニア/面白法人カヤックなどのWeb制作会社に勤務したのち、故郷の新潟に戻り独立。JSフレームワークAngularやFirebase、Google Cloud Platformを使ったWebアプリ開発が得意。 また、Udemyのプログラミング解説の講師、writer.appの自主開発や上越TechMeetupの主催などを行っています。

プロフィール

©Copyright 2022 Yohei Isokawa All Rights Reserved.