投稿者@ pshrmn⬝ オリジナル記事 ⬝ 読書時間 : 10分
React Router v4は、人気のあるReactアドオンの再設計されたバージョンです。 以前のバージョンのプラットフォーム依存のルート構成は削除され、すべてがシンプルなコンポーネントになりました。
このチュートリアルでは、React RouterでWebサイトを構築するために必要なすべてをカバーしています。 地元のスポーツチームのサイトを作成します。
デモを見たいですか?
設置
React Router v4は3つのパッケージに分割されました。
react-router
router-dom
react-router-native
react-router
は、2つの環境(Browserおよびreact-native)で作業するための基本的な機能とコンポーネントを提供します
ブラウザに表示されるサイトを作成するので、
react-router-dom
使用
react-router-dom
必要があります。
react-router-dom
はすべての機能を
react-router
からエクスポートするため、
react-router-dom
をインストール
react-router-dom
だけです。
npm install --save react-router-dom
ルーター
プロジェクトを開始するとき、使用するルーターのタイプを決定する必要があります。 ブラウザープロジェクトには、
BrowserRouter
および
HashRouter
コンポーネントがあります。
BrowserRouter
サーバーで動的リクエストを処理するときに使用し、静的Webサイトがある場合は
HashRouter
を使用する必要があります。
通常、
BrowserRouter
を使用することをお
BrowserRouter
ますが、サイトが静的サーバー( githubページとしての翻訳から )にある場合は、
HashRouter
を使用することが問題の良い解決策です。
このプロジェクトではバックエンドを使用するため、
BrowserRouter
を使用し
BrowserRouter
。
歴史-歴史
各ルーターは、現在の場所[1]へのパスを格納する
history
オブジェクトを作成し、パスの変更が発生したときにサイトインターフェイスを再描画します。
React Routerで提供される残りの機能は、コンテキストを介した
history
オブジェクトの可用性に依存しているため、ルーターコンポーネント内でレンダリングする必要があります。
注:祖先としてルーターコンポーネントを持たないReactルーターコンポーネントは、コンテキストが利用できないため機能しません。
ルーターのレンダリング
Routerコンポーネントは、子として1つの要素のみを想定しています。 この条件下で作業するには、アプリケーション全体をレンダリングする<App />コンポーネントを作成すると便利です(これはサーバーレンダリングにも重要です)。
import { BrowserRouter } from 'react-router-dom'; ReactDOM.render(( <BrowserRouter> <App /> </BrowserRouter> ), document.getElementById('root'))
アプリコンポーネント
アプリケーションは、2つの部分に分割する
<App/>
コンポーネントで始まります。
<Header/>
にはナビゲーションリンクが含まれ、
<Main/>
にはルートのコンテンツが含まれます。
// <Router> const App = () => ( <div> <Header /> <Main /> </div> )
ルート
<Route/>
コンポーネントは、React Routerの主要な構成要素です。 URLのパス名に応じて要素をレンダリングする必要がある場合は、
<Route/>
コンポーネントを使用する必要があります
パス-パス
<Route />
は、特定のパスを記述し、location.pathnameにマップする小道具として
path
を取り
path
。
<Route path='/roster'/>
上記の例では、
<Route/>
は/ roster [2]で始まるlocation.pathnameと一致します。 現在のlocation.pathnameがpropパスにポジティブにマップされると、コンポーネントがレンダリングされ、それらが一致しない場合、Routeは何もレンダリングしません[3]。
<Route path='/roster'/> // location.pathname '/', prop path // location.pathname '/roster' '/roster/2', prop path // exact prop. '/roster', // '/roster/2' <Route exact path='/roster'/>
注:パスに関しては、React Routerはドメインのないパスのみを考慮します。 これは、アドレスで次のことを意味します。
http://www.example.com/my-projects/one?extra=false
React Routerは
/my-projects/one
のみを表示します
パスマッピング
npm
path-to-regexp
パッケージは、propパスを正規表現にコンパイルし、location.pathnameと照合します。 パス行には、ここで説明するよりも複雑な書式設定オプションがあります。 ドキュメントを読むことができます 。
パスが一致する
match
、プロパティを含む
match
オブジェクトが作成されます。
- url-現在のlocation.pathnameのマッピングされた部分
- path -Routeコンポーネントのパス
- isExact-ルートのパス=== location.pathname
- params-オブジェクトには、path-to-regexpモジュールが返すパスからの値が含まれます
注: ルートテスターで遊んで、一致オブジェクトがどのように作成されるかを確認できます。
注:ルートのパスは絶対パスでなければなりません[4]。
ルートを作成する
Route
コンポーネントはルーター内のどこにでも配置できますが、同じ場所に何をレンダリングするかを決定する必要がある場合があります。 この場合、ルートグループ化コンポーネント-
<Switch/>
ます。
<Switch/>
は子コンポーネントを反復処理し、location.pathnameに一致する最初のコンポーネントのみをレンダリングします。
私たちのウェブサイトには、マップしたいパスがあります:
- / -ホームページ
- /名簿 -コマンドページ
- /名簿/:番号 -番号によるプレーヤープロフィールページ
- /スケジュール -チームスケジュール
アプリケーションでパスをマップするために必要なことは、マップするpropパスを使用してRouteコンポーネントを作成することだけです。
<Switch> <Route exact path='/' component={Home}/> {/* /roster /roster/:number /roster */} <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch>
Routeコンポーネントは何をレンダリングしますか?
ルートには、小道具のパスをlocation.pathnameと一致させることでレンダリングする方法を説明する3つの小道具があり、小道具の1つだけをRouteで表す必要があります。
- component -Reactコンポーネント。 ルートがパスに一致すると、渡されたコンポーネントを返します(React.createElement関数を使用)。
- renderは、React要素を返す必要がある関数です。 パス内の一致が満たされたときに呼び出されます。 レンダリングはコンポーネントに非常に似ていますが、インラインレンダリングと必要なprops要素の置換に使用されます[5]。
- children-前の2つの小道具とは異なり、パスがマップされているかどうかに関係なく、子は常に表示されます。
<Route path='/page' component={Page} /> const extraProps = { color: 'red' } <Route path='/page' render={(props) => ( <Page {...props} data={extraProps}/> )}/> <Route path='/page' children={(props) => ( props.match ? <Page {...props}/> : <EmptyPage {...props}/> )}/>
一般的な状況では、コンポーネントを使用するかレンダリングします。 children propは使用できますが、pathがlocation.pathnameと一致しない場合は何もしないことが最善です。
レンダリングされた
Route
は、いくつかの小道具が渡されます。
match
-
path
を
location.pathname
、
location
オブジェクト[6]および
history
オブジェクト(ルート自体によって作成)[7]にマップするオブジェクト。
メイン
次に、ルーターの基本構造について説明します。 ルートをマッピングするだけです。 このアプリケーションでは、
<Main/>
コンポーネント内で
<Switch/>
コンポーネントと
<Route/>
コンポーネントを使用し、内部で
path
一致する生成されたHTMLを配置します。
<Main/>
ノード(ノード)のDOM
import { Switch, Route } from 'react-router-dom' const Main = () => ( <main> <Switch> <Route exact path='/' component={Home}/> <Route path='/roster' component={Roster}/> <Route path='/schedule' component={Schedule}/> </Switch> </main> )
注:メインページの
Route
にはprop
exact
が含まれているため、パスが厳密に比較されます。
継承されたルート
プレーヤープロファイル
/roster/:number
<Switch/>
含まれていません。 代わりに、パスが
/roster
始まるたびにレンダリングされる
<Roster/>
コンポーネントによってレンダリングされます。
Roster
コンポーネントでは、2つのパスのコンポーネントを作成します。
- /名簿 -正確な小道具付き
- / roster /:number-このルートは、/ rosterの後にキャッチされるパスパラメーターを使用します
const Roster = () => ( <Switch> <Route exact path='/roster' component={FullRoster}/> <Route path='/roster/:number' component={Player}/> </Switch> )
共通コンポーネントを持つルートをグループ化すると便利です。これにより、親ルートが簡素化され、複数のルートに関連するコンテンツを表示できます。
たとえば、
<Roster/>
は、
/roster
で始まるすべてのルートに表示されるヘッダーでレンダリングできます。
const Roster = () => ( <div> <h2>This is a roster page!</h2> <Switch> <Route exact path='/roster' component={FullRoster}/> <Route path='/roster/:number' component={Player}/> </Switch> </div> )
パス内のパラメーター
変数を使用して何らかの情報を取得する必要がある場合があります。 たとえば、プレーヤー番号を取得する必要があるプレーヤープロファイルルート。 これを行うには、パラメータを支柱
path
追加します。
:number
/roster/:number
行
:number
部分に
/roster/:number
を
match.params.number
と、
/roster/
後の
path
部分が変数として受信され、
match.params.number
格納され
match.params.number
。 たとえば、path
/roster/6
、パラメーターを使用して次のオブジェクトを生成します。
{ number: '6' // }
<Player/>
コンポーネントは
props.match.params
を使用して、レンダリングする必要がある情報を取得します。
// API import PlayerAPI from './PlayerAPI' const Player = (props) => { const player = PlayerAPI.get( parseInt(props.match.params.number, 10) ) if (!player) { return <div>Sorry, but the player was not found</div> } return ( <div> <h1>{player.name} (#{player.number})</h1> <h2>{player.position}</h2> </div> )
注: path-to-regexpでパスオプションの詳細を確認できます。
<Player/>
コンポーネントに加えて、当社のWebサイトでは
<FullRoster/>
、
<Schedule/>
および
<Home/>
ます。
const FullRoster = () => ( <div> <ul> { PlayerAPI.all().map(p => ( <li key={p.number}> <Link to={`/roster/${p.number}`}>{p.name}</Link> </li> )) } </ul> </div> ) const Schedule = () => ( <div> <ul> <li>6/5 @ </li> <li>6/8 vs </li> <li>6/14 @ </li> </ul> </div> ) const Home = () => ( <div> <h1> !</h1> </div> )
参照資料
最後に、私たちのサイトにはページ間のナビゲーションが必要です。 通常のリンクを作成すると、ページがリロードされます。 React Routerは、再起動を防ぐ
<Link/>
コンポーネントを使用してこの問題を解決します。
<Link/>
をクリックすると、URLが更新され、React Routerはページを更新せずに目的のコンポーネントをレンダリングします。
import { Link } from 'react-router-dom' const Header = () => ( <header> <nav> <ul> <li><Link to='/'>Home</Link></li> <li><Link to='/roster'>Roster</Link></li> <li><Link to='/schedule'>Schedule</Link></li> </ul> </nav> </header> )
<Link/>
はprop
to
使用
to
て、行く先のURLを記述します。 Prop toは、文字列または場所オブジェクト(パス名、検索、ハッシュ、状態のプロパティで構成される)にすることができます。 これが文字列の場合、ロケーションオブジェクトに変換されます。
<Link to={{ pathname: '/roster/7' }}>Player #7</Link>
注:
<Link/>
コンポーネントのパスは絶対パスでなければなりません[4]。
実施例
ウェブサイトのすべてのコードは、codepenのこのアドレスで入手できます。
ルートの準備ができました!
これで、Webアプリケーションのルーティングの詳細に飛び込む準備ができたことを願っています。
独自のWebアプリケーション(
<BrowserRouter.>, <Route.>, and <Link.>
)を作成するときに必要となる最も基本的なコンポーネントを使用しましたが、ここでは説明されていないコンポーネントとプロップがいくつかあります。 幸いなことに、React Routerには優れたドキュメントがあり、コンポーネントや小道具のより詳細な説明を見つけることができます。 ドキュメントには、ソースコードを含む実用的な例も記載されています。
説明
[1]-ロケーションオブジェクトは、URLのさまざまな部分を記述します
// location { pathname: '/', search: '', hash: '', key: 'abc123' state: {} }
[2]-パスなしで
<Route/>
コンポーネントを使用できます。 これは、
context
保存されているメソッドと変数を渡すのに便利です。
[3]-propの
children
を使用する場合、pathとlocation.pathnameが一致しない場合でも、ルートがレンダリングされます。
[4]-
<Route/>
および
<Link/>
相対パスで作業が進行中です。 相対
<Link/>
見た目よりも複雑です。現在のURLではなく、親の
match
オブジェクトを使用して解決する必要があります。
[5]-これはステートレスコンポーネントです。 内部には
render
と
component
間に大きな違いがあり
component
。 コンポーネントは
React.createElement
を使用してコンポーネントを作成し、
render
関数として使用されます。 インライン関数を定義して
props
を渡すと、
render
関数を使用するよりもはるかに遅くなります。
<Route path='/one' component={One}/> // React.createElement(props.component) <Route path='/two' render={() => <Two />}/> // props.render()
[6]-コンポーネント
<Route/> <Switch/>
は両方とも支柱の位置を使用できます。 これにより、実際に現在のURLとは異なるパスにマップすることができます。
[7]
staticContext
も送信しますが、サーバー上でレンダリングする場合にのみ役立ちます。