サイトトップ

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

HTML5テクニカルノート

Create React App + React Router入門 03: ルーティングを入れ子にする


React Routerのルーティングは入れ子にできます。とくにむずかしいことは考えることなく、ルーティングしたコンポーネントの中に、お約束どおりのルーティングを定めればよいのです。前回の「Create React App + React Router入門 02: ページの遷移と状態の保持」でアプリケーションのモジュール(src/App.js)に書いたコード001に手を加えてゆきましょう。

01 コンポーネントにテキストを加える

入れ子のルーティングは、ふたつ目の設定のコンポーネント(Settings2)に加えるつもりです。コンポーネントProductsのタイトルカラーだけでなく、別のテキストも加えられるようにします。そこで、そのテキストをつぎのようにuseState()で状態変数(text2)にもたせました。まずは、コンポーネントにこの新たなテキストが加わります(図001)。

src/App.js

function App() {

	const [text2, setText2] = useState('sample text');
	return (
		<Router>

			<Switch>
				<Route path="/products">
					{/* <Products color2={color2} /> */}
					<Products color2={color2} text2={text2} />
				</Route>

			</Switch>
		</Router>
	);
}

const Products = (props) => (
	<>
		<h2 style={{color: props.color2}}>Products</h2>
		<p>
			{props.text2 ? props.text2 : null}
		</p>
	</>
);

図001■コンポーネントに状態変数のテキストが加わった

図001

02 入れ子のルーティングを定める

入れ子のルーティングは、ルーティング先のコンポーネントの中にさらにルーティングを定めるというだけです。それ以外、とくに変わったところはありません。ルーティングは<Route><Switch>で決めればよく、遷移には<Link>を使ってください。ふたつ目の設定画面のコンポーネント(Settings2)はつぎのように書き替え、ふたつのルーティング先のデータは配列(settings)で定めました。

src/App.js

function App() {function App() {

	const [text2, setText2] = useState('sample text');
	return (
		<Router>

			<Switch>

				<Route path="/settings2">
					{/* <Settings2 setColor2={setColor2} /> */}
					<Settings2 setColor2={setColor2} setText2={setText2} />
				</Route>

			</Switch>
		</Router>
	);
}

/* const Settings2 = (props) => (
	<>
		<h2>Settings2</h2>
		<input type="text"
			onChange={(event) => props.setColor2(event.target.value)}
		/>
		<p><Link to="/settings"><< prev</Link></p>
	</>
); */
const Settings2 = (props) => {
	const settings = [
		{name: 'Color', path: 'color', setValue: props.setColor2},
		{name: 'Text', path: 'text', setValue: props.setText2},
	];
	return (
		<>
			<h2>Settings2</h2>
			<ul>
				{settings.map((setting, id) => (
					<li key={id}>
						<Link to={'/settings2/' + setting.path}>{setting.name}</Link>
					</li>
				))}
			</ul>
			<Switch>
				{settings.map((setting, id) => (
					<Route path={'/settings2/' + setting.path} key={id}>
						<Details name={setting.name} path={setting.path} setValue={setting.setValue} />
					</Route>
				))}
				<Route path={'/settings2/'}>
					<h3>Pleasse select a setting.</h3>
				</Route>
			</Switch>
			<p><Link to="/settings"><< prev</Link></p>
		</>
	);
};

これでProductsコンポーネントのタイトルの色だけでなく、新たに加えたテキストも動的に書き替えられます(図002)。手直ししたアプリケーションモジュールsrc/App.jsの記述全体は、以下のコード001のとおりです。また、サンプル001をCodeSandboxに公開しました。

図002■タイトルカラーだけでなくテキストが動的に書き替えられる

図002左
 → 
図002右

コード001■設定画面で入れ子のルーティングを定める

src/App.js

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');
	const [text2, setText2] = useState('sample text');
	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} text2={text2} />
				</Route>
				<Route path="/settings">
					<Settings setColor={setColor} />
				</Route>
				<Route path="/settings2">
					<Settings2 setColor2={setColor2} setText2={setText2} />
				</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>
		<p>
			{props.text2 ? props.text2 : null}
		</p>
	</>
);
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) => {
	const settings = [
		{name: 'Color', path: 'color', setValue: props.setColor2},
		{name: 'Text', path: 'text', setValue: props.setText2},
	];
	return (
		<>
			<h2>Settings2</h2>
			<ul>
				{settings.map((setting, id) => (
					<li key={id}>
						<Link to={'/settings2/' + setting.path}>{setting.name}</Link>
					</li>
				))}
			</ul>
			<Switch>
				{settings.map((setting, id) => (
					<Route path={'/settings2/' + setting.path} key={id}>
						<Details name={setting.name} path={setting.path} setValue={setting.setValue} />
					</Route>
				))}
				<Route path={'/settings2/'}>
					<h3>Pleasse select a setting.</h3>
				</Route>
			</Switch>
			<p><Link to="/settings">&lt;&lt; prev</Link></p>
		</>
	);
};
const Details = (props) => {
	return (
		<label>
			{props.name}   
			<input type="text"
				onChange={(event) => props.setValue(event.target.value)}
			/>
		</label>
	);
};
export default App;

サンプル001■React Router 04: Nested routing

Create React App + React Router入門


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


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