はじめに
React(react-router-dom)で画面遷移をさせようと思った時にブラウザの表示しているURLは変わるのに画面が遷移しなかったので、その時の対処法を書き残します。
先に原因と対処法が見たい方はこちら
環境
- Ubuntu 20.4
- Node 12.18.3
- npm 6.14.6
- npx 6.14.6
画面遷移させるアプリケーションを作る(現象の再現)
Reactアプリのテンプレートから作成
まずはともかくcreate-react-app
今回はTypeScriptを使用。
npx create-react-app my-app --template typescript
react-router-domのインストール
cd my-app
npm i react-router-dom
npm i --save-dev @types/react-router-dom
画面遷移するアプリケーションへ変更
それぞれのページにボタンを配置し、ボタンをクリックした際にhistory.push()を実行し画面に遷移させる。
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
useHistory
} from "react-router-dom";
import Home from './Home'
import Pages from './Pages'
const App: React.FC = () => {
const history = useHistory()
const goToHome = () => {
history.push('/')
}
const goToPages = () => {
history.push('/pages')
}
return (
<Router>
<Switch>
<Route exact path='/'>
<Home goToPages={goToPages}/>
</Route>
<Route exact path='/pages'>
<Pages goToHome={goToHome}/>
</Route>
</Switch>
</Router>
);
}
export default App;
import React from 'react'
interface Prop {
goToPages: () => void,
}
const Home: React.FC<Prop> = (props) => {
const { goToPages } = props
return (
<div>
<h1>ホームだよ</h1>
<button onClick={goToPages}>Pagesへ</button>
</div>
)
}
export default Home
import React from 'react'
interface Prop {
goToHome: () => void,
}
const Pages: React.FC<Prop> = (props) => {
const { goToHome } = props
return (
<div>
<h1>ページだよ</h1>
<button onClick={goToHome}>ホームへ</button>
</div>
)
}
export default Pages
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router,
} from "react-router-dom";
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
-
index.tsx
- App.tsxで使用しているuseHistoryがRouterコンポーネント内にないと動作しないため、とりあえずRouterで囲う
-
App.tsx
- Switch,Routeによるページ遷移
-
Home.tsx
Pages.tsx
- ページ遷移ボタン設置
そしてnpm start
・・・うーん??
ボタンをクリックした際にURLは変わっているが、画面が変わらない。
リロードをするときちんとそのページが表示される。
#原因と対処法
App.tsx
とindex.tsx
にRouterが重複して存在している。
→Routerの子コンポーネントにRouterが存在している
import React from "react";
import {
Switch,
Route,
useHistory
} from "react-router-dom";
import Home from './Home'
import Pages from './Pages'
function App() {
const history = useHistory()
const goToHome = () => {
history.push('/')
}
const goToPages = () => {
history.push('/pages')
}
return (
<Switch>{/**ここ */}
<Route exact path='/'>
<Home goToPages={goToPages} />
</Route>
<Route exact path='/pages'>
<Pages goToHome={goToHome} />
</Route>
</Switch>
);
}
export default App;
変更して再度実行
・・・いい感じ!!
まとめ
今回はApp.tsx
にページ遷移の関数を作成し、Propsとして渡して実行するというパターンでした。
index.tsx
ではなくApp.tsx
内にBrowserRouter(Router)を配置する際にはそれぞれのページコンポーネント(Home,Pages)にuseHistoryを記述するといいと思います。
アプリケーションにはBrowserRouter(Router)は一つと覚えておくといいと思います。
今後も精進していきます。