react-router-domを使ってReactアプリで画面遷移をしてみる!Material-UIで使う方法も解説!

react-router-domで画面遷移
  • URLをコピーしました!

今回は、react-router-domを使って、Reactアプリで画面遷移をしてみようと思います!
Material-UIでreact-router-domを使う方法も解説しますので、Material-UIを使っている方も参考になると思います!

学習に使った本はこちら!

クマじい

Amazon Kindle Unlimited でもReactの本はいっぱいあるぞ!

  • 技術書をたくさん読みたい!
  • 色々な技術を学びたい!
初回30日間無料体験があるので、どのような参考書があるか確認してみよう!

Kindle Unlimitedで技術書を読むならタブレットがあるとさらに便利ですよ!
10インチあるとより見やすいと思いますが、7インチでも十分見やすくなります!

Reactの開発環境がまだできていない方は、こちらを参考にしてみてください!

サイトデザインに困っている方は、こちらを参考にMaterial-UIを導入してみてもいいと思います!!

画面を切り替えるということは、ほぼ必須だと思いますのでぜひ参考にしてみてください!

キャプション
  • Reactアプリで画面遷移を行いたい!
  • react-router-domの使い方を知りたい!
  • Material-UIでreact-router-domを使う方法が知りたい!
目次

なぜreact-router-domが必要なのか?

クマじい

なぜ、react-router-domが必要なんじゃ??

Reactアプリで画面遷移を行うために、なぜreact-router-domが必要なのかを少し説明しようと思います!

ReactはSPA(シングルページアプリケーション)を得意としているフレームワークです。
SPAは、初期ロード時に全ての情報を読み込むことで、初期ロード時に時間がかかってしまうが、一度ロードしてしまえばページリクエストをすることがなく動作スピードが向上します。

しかし、ページリクエストをしないので画面遷移をすることができなくなってしまいます。
それを解消するのがreact-router-domです。

Routingという機能を提供し、DOMを書き換えて複数ページがあるようにしてあげることを可能にしてくれます!

react-router-domを使ってみよう!

なぜ、react-router-domを使う必要があるのかを説明したので、早速実装してみましょう!!

react-router-domをインストールしていく!

まずは、react-router-domをnpmを使ってインストールしていきます!
下記のコマンドを実行してください!

C:\Users\*****\Documents\sample-react-app>npm install react-router-dom

コマンドを実行したら、package.jsonにreact-router-domが追記されていると思います!

package.json

{
  "name": "sample-client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^4.11.3",
    "@material-ui/icons": "^4.11.2",
    "@testing-library/jest-dom": "^5.11.9",
    "@testing-library/react": "^11.2.5",
    "@testing-library/user-event": "^12.7.1",
    "axios": "^0.21.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-router-dom": "^5.2.0",
    "react-scripts": "4.0.2",
    "web-vitals": "^1.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {}
}

ここまで確認できれば、インストールは完了です!

Linkを設定する!

Linkはreact-router-domのコンポーネントで、指定したpathにアクセスする設定をします!

せっかくなので、前回作ったヘッダーにボタンを配置してLinkを設定していきます!
もし、この記事から見始めるひとは、任意の場所にボタンを配置してLinkを設定してみてください!

Header.jsを開いて、下記のように修正します!

import でreact-router-domのLinkコンポーネントをインポートしています。
<Link>のtoに、アクセスしたいPathを記載します!

Header.js

import React from 'react'
import { Link } from 'react-router-dom'

import { makeStyles, withStyles } from '@material-ui/core/styles'
import {
  AppBar,
  Toolbar,
  Typography,
  Button,
  IconButton,
  Box,
} from '@material-ui/core'
import { Menu as MenuIcon } from '@material-ui/icons'

const useStyles = (theme) => ({
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginRight: theme.spacing(2),
  },
  title: {
    flexGrow: 1,
  },
})

class Header extends React.Component {
  render() {
    const { classes } = this.props
    return (
      <div className={classes.root}>
        <AppBar position="relative">
          <Toolbar>
            <IconButton
              edge="start"
              className={classes.menuButton}
              color="inherit"
              aria-label="menu"
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="h6" className={classes.title}>
              <Box textAlign="left">SampleTitle</Box>
            </Typography>
            <Button color="inherit">
              <Link to="/sample1">sample1</Link>
            </Button>
            <Button color="inherit">
              <Link to="/sample2">sample2</Link>
            </Button>
          </Toolbar>
        </AppBar>
      </div>
    )
  }
}

RouterとRouteを設定していく!

続いて、RouterとRouteを設定していきます。

Routerは、react-router-domのコンポーネント(Route,Link)を使えるようにするためのコンポーネントです。
なので、上位の階層(App.jsなど)で設定することが多いです。

Routeは、pathに指定したURLと現在のURLが一致するときにUIを表示させてあげるコンポーネントです。

App.jsを下記のように修正し、いくつかSample画面を作成しておきます!

App.js

import './App.css'
import { BrowserRouter as Router, Route } from 'react-router-dom'

import Header from './components/modules/Header'
import SampleRoot from './components/pages/SampleRoot'
import Sample1 from './components/pages/Sample1'
import Sample2 from './components/pages/Sample2'

function App() {
  return (
    <div className="App">
      <Router>
        <Header />
        <Route path="/" component={SampleRoot} />
        <Route path="/sample1" component={Sample1} />
        <Route path="/sample2" component={Sample2} />
      </Router>
    </div>
  )
}

export default App

サンプルの画面は、components>modules>pages配下に作成してください!

SampleRoot.js

import React from 'react'

class SampleRoot extends React.Component {
  render() {
    return <div>Rootで表示されてほしい内容!</div>
  }
}

export default SampleRoot

Sample1.js

import React from 'react'

class Sample1 extends React.Component {
  render() {
    return <div>sample1で表示されてほしい内容!</div>
  }
}

export default Sample1

Sample2.js

import React from 'react'

class Sample2 extends React.Component {
  render() {
    return <div>sample2で表示されてほしい内容!</div>
  }
}

export default Sample2

ここまでできれば、設定は完了なので実際に確認してみましょう!

確認してみる!

まずは、「http://localhost:3000」を確認しましょう!

(j) localhost 
C 
:3000 
SampleTitle 
SAMPLE' 
SAMPLE-z

ヘッダーの右端に、SAMPLE1とSAMPLE2というボタンが表示されていますね!!
また、path=”/”の内容である、SampleRoot.jsが表示されていると思います!

続いて、SAMPLE1のボタンを押してみましょう!
「http://localhost:3000/sample1」に遷移すると思います!

← 
0 
( ① localhost:3000/sample1 
SampleTitle 
Root て 表 示 さ れ て ほ し い 内 容 ! 
sam el て 表 示 さ れ て ほ し い 内 容 ! 
a あ 
SAMPLEZ


ただ、画面は、path=”/sample1″の内容だけでなく、path=”/”も表示されてしまっていると思います。

念のため、SAMPLE2も確認してみましょう!
「http://localhost:3000/sample2」に遷移はすると思います。

← 
0 
( ① localhost:3000/sample2 
SampleTitle 
Root て 表 示 さ れ て ほ し い 内 容 ! 
sam e2 て 表 示 さ れ て ほ し い 内 容 ! 
a あ 
SAMPLEZ

こちらも、画面は、path=”/sample2″の内容だけでなく、path=”/”も表示されてしまっていますね。

なぜかというと、 <Link>のpathは、部分一致なので 「/sample1」だと 「/」も「/sample1」も一致したとみなされてしまうのです。

pathを完全一致にしてみよう!

では、完全一致にするにはどうしたらいいかというと、exactをつけてあげればいいだけです!

App.jsを下記のように修正してみてください!

App.js

import './App.css'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Header from './components/modules/Header'
import SampleRoot from './components/pages/SampleRoot'
import Sample1 from './components/pages/Sample1'
import Sample2 from './components/pages/Sample2'

function App() {
  return (
    <div className="App">
      <Router>
        <Header />
        <Route exact path="/" component={SampleRoot} />
        <Route exact path="/sample1" component={Sample1} />
        <Route exact path="/sample2" component={Sample2} />
      </Router>
    </div>
  )
}

export default App

これで再度確認してみましょう!

C 
(j) localhost 
:3000 
SampleTitle 
SAMPLE' 
SAMPLE-z

「http://localhost:3000」の時は、前回と同様にpath=”/”のSampleRoot.jsの内容のみが表示されていますね!

C 
(j) localhost:3000/sample1 
SampleTitle 
SAMPLE' 
SAMPLE-z

「http://localhost:3000/sample1」の時も、path=”/sample1″のSample1.jsの内容のみが表示されていることが確認できたと思います!

C 
(j) localhost:3000/sample2 
SampleTitle 
SAMPLE' 
SAMPLE-z

「http://localhost:3000/sample2」の時も、path=”/sample2″のSample2.jsの内容のみが表示されていることが確認できてますよね!

ボタンを修正しよう!

先ほどLinkを設定したボタンを、よくみてもらうとわかるのですがリンク表示されてしまっていますよね。
Material-UIでreact-router-domのLinkを設定する場合の記述と異なるために起きてしまっているので、これを修正していこうと思います。

Material-UIを使っていない方は、飛ばしてもらって構いません!

Header.jsを下のように修正します!

Header.js

import React from 'react'
import { Link } from 'react-router-dom'

import { makeStyles, withStyles } from '@material-ui/core/styles'
import {
  AppBar,
  Toolbar,
  Typography,
  Button,
  IconButton,
  Box,
} from '@material-ui/core'
import { Menu as MenuIcon } from '@material-ui/icons'

const useStyles = (theme) => ({
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginRight: theme.spacing(2),
  },
  title: {
    flexGrow: 1,
  },
})

class Header extends React.Component {
  render() {
    const { classes } = this.props
    return (
      <div className={classes.root}>
        <AppBar position="relative">
          <Toolbar>
            <IconButton
              edge="start"
              className={classes.menuButton}
              color="inherit"
              aria-label="menu"
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="h6" className={classes.title}>
              <Box textAlign="left">SampleTitle</Box>
            </Typography>
            <Button color="inherit" component={Link} to="/sample1">
              sample1
            </Button>
            <Button color="inherit" component={Link} to="/sample2">
              sample2
            </Button>
          </Toolbar>
        </AppBar>
      </div>
    )
  }
}

export default withStyles(useStyles)(Header)

Material-UIのButtonコンポーネントにcomponent={Link} to=”Path”を指定することでMaterial-UIでLinkを使うことが可能になります。
これで、確認してみましょう!

← 
0 
① localhost 
: 3000 
SampleTitle 
Root て 表 示 さ れ て ほ し い 内 容 ! 
a あ 
SAMPLEI 
SAMPLE2

ちゃんとリンク表記ではない表記になりましたね!!

【おまけ】Switchを使ってみる!

先ほど、exactを使うと完全一致になると説明したと思いますが、もし完全一致が複数ある場合(こんなことはまずないと思いますが)は、どうなるでしょうか。

App.js

import './App.css'
import { BrowserRouter as Router, Route } from 'react-router-dom'
import Header from './components/modules/Header'
import SampleRoot from './components/pages/SampleRoot'
import Sample1 from './components/pages/Sample1'
import Sample2 from './components/pages/Sample2'

function App() {
  return (
    <div className="App">
      <Router>
        <Header />
        <Route exact path="/" component={SampleRoot} />
        <Route exact path="/sample1" component={Sample1} />
        <Route exact path="/sample1" component={Sample1} />
        <Route exact path="/sample2" component={Sample2} />
      </Router>
    </div>
  )
}

export default App

こんなコードだった場合に、どうなるか確認してみましょう!

← 
C 〇 10 ( h05t3000 / 5 ョ mp 1 
SampleTitle 
5 ョ mp 1 で 表 示 さ れ て ほ し い 内 容 ! 
5 ョ mp 1 で 表 示 さ れ て ほ し い 内 容 ! 
a あ 
SAMPLEI SAMPLE2

一致しているもの全てを表示することになってしまいますね。

これはこれでいいのですが、Switchを使うことで最初に一致したものだけを表示するということが可能になります。

App.js

import './App.css'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import Header from './components/modules/Header'
import SampleRoot from './components/pages/SampleRoot'
import Sample1 from './components/pages/Sample1'
import Sample2 from './components/pages/Sample2'

function App() {
  return (
    <div className="App">
      <Router>
        <Header />
        <Switch>
          <Route exact path="/" component={SampleRoot} />
          <Route exact path="/sample1" component={Sample1} />
          <Route exact path="/sample1" component={Sample1} />
          <Route exact path="/sample2" component={Sample2} />
        </Switch>
      </Router>
    </div>
  )
}

export default App

こんな感じで、Switch を追加してみてください!

C Q) localhost:3000/sampIe1 
SampleTitle 
SAMPLEI SAMPLE2

すると、最初の1つ目に一致したものだけが表示されると思います。

URL定義をちゃんとしていれば、必要のない機能だと思いますのでおまけにしましたが、
応用次第で色々なことができると思います!

まとめ

今回は、reace-router-domを使って、Reactアプリで画面遷移を行う方法を説明いたしました!
DOMを更新するだけなので、画面がロードされていないことも確認できたかなと思います!!

ほぼ必須と言っても過言ではない機能なので、ぜひ覚えてみてください!

学習に使った本はこちら!

クマじい

Amazon Kindle Unlimited でもReactの本はいっぱいあるぞ!

  • 技術書をたくさん読みたい!
  • 色々な技術を学びたい!
初回30日間無料体験があるので、どのような参考書があるか確認してみよう!

Kindle Unlimitedで技術書を読むならタブレットがあるとさらに便利ですよ!
10インチあるとより見やすいと思いますが、7インチでも十分見やすくなります!

次回は、APIを呼び出してデータを取得してみようと思います!

react-router-domで画面遷移

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

東京在住で20代のエンジニアです。
特に特技があるわけではありませんが、誰もが楽しくプログラミングができたらいいと思い、「teech lab.」を開設いたしました。

Enjoy Diaryという、ガジェットや雑貨を紹介しているブログもあります!
ぜひ、みてください!!

目次