react-router
は、React
で構築されたシングルページアプリケーションでルーティング機能を簡単に実装できる、シンプルかつ強力なAPIを提供します。
まず、簡単な例を見てみましょう。
import React from "react";
import { findDOMNode, render } from "react-dom";
import { Link, Route, Router } from "react-router";
let Page1 = React.createClass({
render() {
return (
<div>
<h1>Page1</h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Ab accusantium animi dicta dignissimos earum eos esse impedit ipsum iste
laboriosam numquam odio perspiciatis porro, quas sequi tempore vero
vitae voluptates?
</div>
);
},
});
let Page2 = React.createClass({
render() {
return (
<div>
<h1>Page2</h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Fuga porro voluptas voluptatum. Corporis debitis deleniti, doloremque et
eum ex id iste magni nobis nostrum quae, reiciendis rem repellendus
similique tempora.
</div>
);
},
});
let App = React.createClass({
render() {
return (
<div>
<Link to="/page1">Page1</Link>
<Link to="/page2">Page2</Link>
</div>
);
},
});
render(
<Router>
<Route path="/" component={App}>
<Route path="page1" component={Page1} />
<Route path="page2" component={Page2} />
</Route>
</Router>,
document.body,
);
<Link>
タグのto
属性にパスを定義するだけで、レンダリングされたページでPage1またはPage2のタグをクリックすると、対応するComponents
が表示され、url
もパスに応じて変化します。
このコードを簡単に分析してみましょう。ここでは3つのルートを定義しています。1つはルートディレクトリ、つまり/
を指し、もう1つはpage/
を、そしてもう1つはpage/2
を指しています。
ルートの定義は<Router></Router>
で囲む必要があります。
<Route></Route>
は、各ルートで定義するパスと、その動作を処理するためのものです。path
はパスを、component
はレンダリングするコンポーネントを示します。また、ルートの動作を制御するためのhandle
も提供できます。
次に、ログインをインターセプトする動作をシミュレートしてみましょう。
import React from "react";
import TransitionGroup from "react-addons-transition-group";
import { findDOMNode, render } from "react-dom";
import { History, Link, Route, Router } from "react-router";
require("./index.css");
let goLogin = {
isLogin: true,
login() {
this.isLogin ? this.onChange(false) : this.onChange(true);
this.isLogin = !this.isLogin;
},
onChange() {},
};
let App = React.createClass({
getInitialState() {
return {
login: goLogin.isLogin,
};
},
updateAuth(logged) {
this.setState({
login: logged,
});
},
componentWillMount() {
goLogin.onChange = this.updateAuth;
},
render() {
return (
<div>
<nav className="nav">
{this.state.login ? (
<Link to="/logout">Log out</Link>
) : (
<Link to="/login">Log in</Link>
)}
</nav>
<ul>
<li>
<Link to="/page1" activeClassName="active">
Page1
</Link>
</li>
<li>
<Link to="/page2" activeClassName="active">
Page2
</Link>
</li>
</ul>
{this.props.children}
</div>
);
},
});
let Login = React.createClass({
mixins: [History],
handleClick(event) {
event.preventDefault();
goLogin.login();
var { location } = this.props;
if (location.state && location.state.nextPathname) {
this.history.replaceState(null, location.state.nextPathname);
} else {
this.history.replaceState(null, "/about");
}
console.log(this.history);
},
render() {
return (
<div>
<button onClick={this.handleClick}>Login</button>
</div>
);
},
});
let Logout = React.createClass({
componentDidMount() {
goLogin.login();
},
render() {
return (
<div>
<p>You are now logged out</p>
</div>
);
},
});
let About = React.createClass({
render() {
return (
<div>
<h1>登录成功</h1>
</div>
);
},
});
let Page1 = React.createClass({
render() {
return (
<div className="page">
<h1>Page1</h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Ab accusantium animi dicta dignissimos earum eos esse impedit ipsum iste
laboriosam numquam odio perspiciatis porro, quas sequi tempore vero
vitae voluptates?
</div>
);
},
});
let Page2 = React.createClass({
getInitialState() {
return {
className: "pageactive",
};
},
handler() {
if (this.state.className === "pageactive") {
this.setState({
className: "",
});
} else {
this.setState({
className: "pageactive",
});
}
},
render() {
return (
<div className={`${this.state.className} page`} onClick={this.handler}>
<h1>Page2</h1>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Fuga porro voluptas voluptatum. Corporis debitis deleniti, doloremque et
eum ex id iste magni nobis nostrum quae, reiciendis rem repellendus
similique tempora.
</div>
);
},
});
needLogin
関数を定義し、ユーザーがログインしているかどうかを判断し、状況に応じて適切なページにリダイレクトします。
function needLogin(nextState, replaceState) {
if (!goLogin.isLogin) {
replaceState({ nextPathname: nextState.location.pathname }, "/login");
}
}
最後に、render
コマンドを実行します。
render(
<Router>
<Route path="/" component={App}>
<Route path="login" component={Login} />
<Route path="logout" component={Logout} />
<Route path="about" component={About} />
<Route path="page1" component={Page1} />
<Route path="page2" component={Page2} onEnter={needLogin} />
</Route>
</Router>,
document.body,
);
DEMOはこちらをクリック このコードは、以下の機能を実装しています。
- ページはデフォルトで未ログイン状態です。
- この状態でPage1をクリックすると、Page1の内容が表示されます。
- Page2をクリックすると、ページ内容の表示がインターセプトされ、ログインページが表示されます。
login
をクリックすると、Page2の内容が表示され、状態がLogout
に切り替わります。Logout
をクリックすると、ログアウトします。
このコードでは、page2
をクリックすると、まず<Link>
タグのto
属性がトリガーされ、path
がpage2
である対応するルートが検索され、その後needLogin
イベントがトリガーされます。
needLogin
イベントでは、goLogin.isLogin
イベントを判断し、未ログインの場合はパスを/login
に置き換えます。
そして、<Route>
の中からpath
が/login
である項目を見つけ、Login
コンポーネントをレンダリングします。
つまり、<Route>
内でイベントをリッスンすることで、必要に応じて動的にルーティングアドレスを変更できるということです。
この記事は 2015年10月9日 に公開され、2015年10月9日 に最終更新されました。3650 日が経過しており、内容が古くなっている可能性があります。