HTML5テクニカルノート
Create React App + React Router入門 02: ページの遷移と状態の保持
- ID: FN2005002
- Technique: ECMAScript 2015
- Library: React 16.13.1 / React Router 5.1.2
シングルページアプリケーション(SPA)には、状態をもたせることができ、それに応じてコンポーネントの表示が変えられます。今回確かめるのは、ルーティングで状態がどのように扱われるのかということです。前回アプリケーションのモジュール(src/App.js
)に書いたコード002に手を加えてゆきましょう。
01 テキストのカラーを設定する
ホームのコンポーネント(Home
)のテキストカラーを、ステートフックuseState()
でもたせた状態変数(color
)でつぎのように定めます。ホームのテキストが指定した色に変わりました(図001)。ステートフックについては、「React Hooks: クラスのコンポーネントをuseState()で関数に書き替える」02「ステートフックuseState()を使う」をお読みください。
src/App.js// import React from 'react'; import React, { useState } from 'react'; function App() { const [color, setColor] = useState('blue'); return ( <Router> <Switch> <Route path="/"> {/* <Home /> */} <Home color={color} /> </Route> </Switch> </Router> ); } // const Home = () => ( const Home = (props) => ( // <h2>Home</h2> <h2 style={{color: props.color}}>Home</h2> );
図001■テキストのカラーが設定される
02 カラーを動的に変える
カラーの状態変数値(color
)は、設定のコンポーネント(Settings
)から変えられるようにします。テキストフィールド(<input type="text">
要素)の入力(onChange
イベント)により呼び出しているのが状態の設定関数(setColor()
)です。文字列で打ち込んだカラー名あるいはカラー値にもとづいて、ホームのテキストの色が動的に変わります(図002)。
src/App.jsfunction App() { const [color, setColor] = useState('black'); // blue'); return ( <Router> <Switch> <Route path="/settings"> {/* <Settings /> */} <Settings setColor={setColor} /> </Route> </Switch> </Router> ); } // const Settings = () => ( const Settings = (props) => ( <> <h2>Settings</h2> <input type="text" onChange={(event) => props.setColor(event.target.value)} /> </> );
図002■テキストのカラーが動的に変わる
03 コンポーネントの遷移と状態
設定画面のコンポーネント(Settings2
)をもうひとつ増やします。ただし、上部(<ul>
要素)のリンク項目には加えません。ひとつ目の設定コンポーネント(Settings
)から、つぎのように<a>
要素で遷移することにします。結論として、ここで<a>
要素を用いるのは適切ではありません。この場合何が起こって、何が起こらないのかを、確かめてみようということです。
src/App.jsfunction App() { return ( <Router> <Switch> <Route path="/settings2"> <Settings2 /> </Route> </Switch> </Router> ); } const Settings = (props) => ( <> <p><a href="/settings2">next >></a></p> </> ); const Settings2 = () => ( <h2>Settings2</h2> );
試してみてわかるのは、ひとたびふたつ目の設定画面に移ると、テキストカラー(black)がもとに戻ってしまうことです。何が起きているのか確かめるため、public/index.html
に、つぎのようなJavaScriptコードを加えてみましょう。
public/index.html<title>React App</title> <script> console.log('page loaded!'); </script>
ページが読み込まれると、ブラウザコンソールにテキスト(page loaded!)が出力されます。画面上部(<ul>
要素)のリンクでルーティングしているかぎり、改めてテキストが示されることはありません。ところが、設定のコンポーネント(Settings
)から<a>
要素で遷移すると、テキストが出力されます。つまり、ページがリロードされて、カラーの状態変数(color
)も初期値に戻ってしまったということです。
04 ルーティングはLinkコンポーネントで行う
ルーティングは<a>
要素でなく、Link
コンポーネントで行わなければなりません。設定のコンポーネント(Settings
)の記述を改めるとともに、ふたつ目の設定のコンポーネント(Settings2
)はまた別のコンポーネント(Products
)のテキストカラーが変えられるように書き加えましょう。
src/App.jsfunction App() { const [color2, setColor2] = useState('black'); return ( <Router> <Switch> <Route path="/products"> {/* <Products /> */} <Products color2={color2} /> </Route> <Route path="/settings2"> {/* <Settings2 /> */} <Settings2 setColor2={setColor2} /> </Route> </Switch> </Router> ); } // const Products = () => ( const Products = (props) => ( // <h2>Products</h2> <h2 style={{color: props.color2}}>Products</h2> ); const Settings = (props) => ( <> {/* <p><a href="/settings2">next >></a></p> */} <p><Link to="/settings2">next >></Link></p> </> ); // const Settings2 = () => ( const Settings2 = (props) => ( <> <input type="text" onChange={(event) => props.setColor2(event.target.value)} /> <p><Link to="/settings">><< prev</Link></p> </> );
どちらの設定画面で定めたテキストカラーも、ルーティングによって失われることはなくなりました(図003)。ページがリロードされなくなったからです。モジュールsrc/App.css
の記述は以下のコード001にまとめ、サンプル001はCodeSandboxに公開しました。
図003■ふたつ目の設定画面で別のコンポーネントのテキストカラーを変える
コード001■設定画面で別のコンポーネントのテキストカラーを変える
src/App.css
import React, { useState } from 'react';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from 'react-router-dom';
import './App.css';
function App() {
const [color, setColor] = useState('black');
const [color2, setColor2] = useState('black');
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/products">Products</Link>
</li>
<li>
<Link to="/settings">Settings</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/products">
<Products color2={color2} />
</Route>
<Route path="/settings">
<Settings setColor={setColor} />
</Route>
<Route path="/settings2">
<Settings2 setColor2={setColor2} />
</Route>
<Route path="/">
<Home color={color} />
</Route>
</Switch>
</Router>
);
}
const Home = (props) => (
<h2 style={{color: props.color}}>Home</h2>
);
const Products = (props) => (
<h2 style={{color: props.color2}}>Products</h2>
);
const Settings = (props) => (
<>
<h2>Settings</h2>
<input type="text"
onChange={(event) => props.setColor(event.target.value)}
/>
<p><Link to="/settings2">next >></Link></p>
</>
);
const Settings2 = (props) => (
<>
<h2>Settings2</h2>
<input type="text"
onChange={(event) => props.setColor2(event.target.value)}
/>
<p><Link to="/settings"><< prev</Link></p>
</>
);
export default App;
サンプル001■React Router 03: Routing and States
Create React App + React Router入門
- Create React App + React Router入門 01: ルーティングを定める
- Create React App + React Router入門 02: ページの遷移と状態の保持
- Create React App + React Router入門 03: ルーティングを入れ子にする
- Create React App + React Router入門 04: フックuseRouteMatch()とuseHistory()を使う
作成者: 野中文雄
作成日: 2020年05月10日
Copyright © 2001-2020 Fumio Nonaka. All rights reserved.