サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

Create React App + React Router入門 02: ページの遷移と状態の保持


シングルページアプリケーション(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■テキストのカラーが設定される

図001

02 カラーを動的に変える

カラーの状態変数値(color)は、設定のコンポーネント(Settings)から変えられるようにします。テキストフィールド(<input type="text">要素)の入力(onChangeイベント)により呼び出しているのが状態の設定関数(setColor())です。文字列で打ち込んだカラー名あるいはカラー値にもとづいて、ホームのテキストの色が動的に変わります(図002)。

src/App.js

function 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■テキストのカラーが動的に変わる

図002左
 → 
図002右

03 コンポーネントの遷移と状態

設定画面のコンポーネント(Settings2)をもうひとつ増やします。ただし、上部(<ul>要素)のリンク項目には加えません。ひとつ目の設定コンポーネント(Settings)から、つぎのように<a>要素で遷移することにします。結論として、ここで<a>要素を用いるのは適切ではありません。この場合何が起こって、何が起こらないのかを、確かめてみようということです。

src/App.js

function App() {

	return (
		<Router>

			<Switch>

				<Route path="/settings2">
					<Settings2 />
				</Route>

			</Switch>
		</Router>
	);
}

const Settings = (props) => (
	<>

		<p><a href="/settings2">next &gt;&gt;</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.js

function 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 &gt;&gt;</Link></p>
	</>
);
// const Settings2 = () => (
const Settings2 = (props) => (
	<>

		<input type="text"
			onChange={(event) => props.setColor2(event.target.value)}
		/>
		<p><Link to="/settings">&gt;&lt;&lt; prev</Link></p>
	</>
);

どちらの設定画面で定めたテキストカラーも、ルーティングによって失われることはなくなりました(図003)。ページがリロードされなくなったからです。モジュールsrc/App.cssの記述は以下のコード001にまとめ、サンプル001はCodeSandboxに公開しました。

図003■ふたつ目の設定画面で別のコンポーネントのテキストカラーを変える

図003左
 → 
図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 &gt;&gt;</Link></p>
	</>
);
const Settings2 = (props) => (
	<>
		<h2>Settings2</h2>
		<input type="text"
			onChange={(event) => props.setColor2(event.target.value)}
		/>
		<p><Link to="/settings">&lt;&lt; prev</Link></p>
	</>
);
export default App;

サンプル001■React Router 03: Routing and States

Create React App + React Router入門


作成者: 野中文雄
作成日: 2020年05月10日


Copyright © 2001-2020 Fumio Nonaka.  All rights reserved.