React Router: IndexRouteはもう古い? 最新の代替方法とサンプルコードで徹底解説
React Router における IndexRoute の役割
具体的には、以下の様な役割を果たしていました。
- 逆に、
/users/profile
または/users/settings
にアクセスすると、それぞれのサブルートに対応するコンポーネントがレンダリングされます。 - この場合、
/users
にアクセスすると、IndexRoute に指定されたデフォルトの子コンポーネントがレンダリングされます。 - 例えば、
/users
という親ルートと/users/profile
、/users/settings
などのサブルートがあると仮定します。 - 親ルートに複数のサブルートがある場合、どのサブルートもアクティブではない場合にデフォルトの子コンポーネントをレンダリングする
- 親ルートにアクセスされた場合、自動的に指定された子コンポーネントをレンダリングする
React Router v4 以降では、IndexRoute は廃止され、代わりに以下の方法で同じ機能を実現することができます。
- 例えば、以下のコードは、
/
にアクセスされた際にHome
コンポーネントをレンダリングします。 - 親ルートに
path="/"
を指定し、その中にレンダリングしたいデフォルトの子コンポーネントを配置する
<BrowserRouter>
<div>
<Route path="/" exact component={Home} />
<Route path="/users" component={Users} />
</div>
</BrowserRouter>
IndexRoute と上記の方法の主な違いは以下の通りです。
- IndexRoute は親ルートにのみ使用できましたが、新しい方法はどのルートでも使用できます。
- IndexRoute は専用のコンポーネントでしたが、新しい方法は Route コンポーネントの
path
とexact
props を使用して実現します。
- React Router v4 以降では、IndexRoute は廃止され、代わりに
path="/"
とexact
props を使用して同じ機能を実現することができます。 - 親ルートのURLにアクセスされた際に、デフォルトの子コンポーネントをレンダリングするために使用されていました。
- IndexRoute は React Router の古いバージョンで使用されていた機能です。
import React from 'react';
import { BrowserRouter, Route, IndexRoute } from 'react-router-dom';
const App = () => (
<BrowserRouter>
<div>
<Route path="/" component={Home} />
<Route path="/users" component={Users}>
<IndexRoute component={UserList} />
<Route path="/:userId" component={UserDetails} />
</Route>
</div>
</BrowserRouter>
);
const Home = () => <h1>Home</h1>;
const Users = () => <h1>Users</h1>;
const UserList = () => <h2>User List</h2>;
const UserDetails = ({ userId }) => (
<div>
<h2>User Details: {userId}</h2>
</div>
);
export default App;
このコードの説明
UserDetails
コンポーネントは、URL パラメータuserId
を使用して特定のユーザーの詳細を表示します。/users
ルートには、Users
コンポーネントがレンダリングされます。/
ルートには、Home
コンポーネントがレンダリングされます。- アプリケーションには、
/
、/users
、/users/:userId
の3つのルートがあります。 - このコードは、React Router v3 を使用してシンプルなブログアプリケーションを作成しています。
React Router v4
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
const App = () => (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/users" component={Users} />
</Switch>
</BrowserRouter>
);
const Home = () => <h1>Home</h1>;
const Users = () => (
<div>
<h2>Users</h2>
<Route path="/users/:userId" component={UserDetails} />
</div>
);
const UserDetails = ({ userId }) => (
<div>
<h2>User Details: {userId}</h2>
</div>
);
export default App;
/users
ルートには、Users
コンポーネントをレンダリングするように指定しています。Users
コンポーネント内には、/users/:userId
ルートにマッチする際にUserDetails
コンポーネントをレンダリングするようにネストしています。
/
ルートには、path="/"
とexact
props を使用してHome
コンポーネントをデフォルトでレンダリングするように指定しています。- React Router v4 では、
IndexRoute
は廃止され、代わりにexact
props を使用してデフォルトの子コンポーネントを指定することができます。
- どちらのバージョンも、基本的なルーティング機能を提供しますが、React Router v4 の方が簡潔で読みやすいコードとなっています。
この方法は、IndexRoute
を使用するよりも簡潔で読みやすいコードとなるため、推奨されています。
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
const App = () => (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/users" component={Users} />
</Switch>
</BrowserRouter>
);
// コンポーネントは変更ありません
const Home = () => <h1>Home</h1>;
const Users = () => <h1>Users</h1>;
// ...
export default App;
useContext
フックとデフォルトコンテキスト
useContext
フックとデフォルトコンテキストを使用する方法もあります。この方法は、より汎用的なアプローチですが、設定が少し複雑になります。
まず、デフォルトコンテキストを作成する必要があります。
const DefaultContext = React.createContext({
component: Home, // デフォルトコンポーネント
});
次に、DefaultContext
をコンポーネントツリー全体に提供する必要があります。
const App = () => (
<DefaultContext.Provider value={{ component: Home }}>
<BrowserRouter>
<Switch>
<Route path="/" exact component={RouteComponent} />
<Route path="/users" component={Users} />
</Switch>
</BrowserRouter>
</DefaultContext.Provider>
);
最後に、各ルートコンポーネントで useContext
フックを使用してデフォルトコンポーネントを取得し、条件に応じてレンダリングします。
const RouteComponent = () => {
const { component } = useContext(DefaultContext);
return <component />;
};
上記以外にも、デフォルトの子コンポーネントをレンダリングする方法はいくつかあります。
- 高階コンポーネントを使用する
- レンダリングプロップを使用する
- カスタムフックを使用する
これらの方法は、より高度なユースケース向けに適しています。
React Router でデフォルトの子コンポーネントをレンダリングするには、いくつかの方法があります。
- 高階コンポーネント
- レンダリングプロップ
- カスタムフック
Switch
コンポーネントとexact
属性 (推奨)
javascript reactjs react-router