ネストしたルートに遷移するとき、 遷移先のルートに対応するコンポーネントが、親コンポーネントの props.children にセットされている。
ここで props.children をそのまま表示せずに、 React.cloneElement で props.children を複製すると、 その際に props を渡せる。
もっとスマートな方法が提供されていたらいいんだけど、 今のところこの方法しか無さそう。
何はともあれ、ルートコンポーネントのみに状態を持たせ、子コンポーネントはステートレスにできた。
var React = require("react"); var ReactDOM = require("react-dom"); var ReactRouter = require("react-router"); var Router = ReactRouter.Router; var Link = ReactRouter.Link; var Route = ReactRouter.Route; var IndexRoute = ReactRouter.IndexRoute; var User = React.createClass({ // ID は URL に埋め込む。 // クエリパラメータで名前を渡す。 render: function() { return ( <tr> <td> <Link to={"/users/" + this.props.user.id} query={{name: this.props.user.name}}> {this.props.user.name} </Link> </td> </tr> ); } }); var Users = React.createClass({ getUsers: function() { return this.props.users.map(function(u) { return <User user={u} />; }); }, render: function() { return ( <div className="users"> <h1>ユーザー一覧</h1> <table> <thead> <tr> <th>名前</th> </tr> </thead> <tbody> {this.getUsers()} </tbody> </table> </div> ); } }); var UserDetail = React.createClass({ render: function() { // パスに埋め込まれたパラメータは params から取得できる var userId = this.props.params.id; // ユーザーを取得 var user = this.props.users[userId - 1]; // 名前はクエリパラメータで受け取ったものを表示してみる return ( <div className="user-detail"> <h1>ユーザー詳細</h1> <dl> <dt>ID</dt> <dd>{user.id}</dd> <dt>名前</dt> <dd>{this.props.location.query.name}</dd> <dt>年齢</dt> <dd>{user.age}</dd> </dl> </div> ); } }); var About = React.createClass({ render: function() { return ( <div className="about"> <h1>このサンプルについて</h1> <p>react-router のサンプルです。</p> </div> ); } }); var MyApp = React.createClass({ getInitialState: function() { // ルートコンポーネントだけが状態を持つ return { users: [ { id: 1, name: "香川", age: 26 }, { id: 2, name: "本田", age: 29 }, { id: 3, name: "長友", age: 29 }, { id: 4, name: "岡崎", age: 29 }, { id: 5, name: "内田", age: 28 }, { id: 6, name: "清武", age: 25 } ] }; }, render: function() { // children の要素をクローンして描画する。 // その際に props を渡す。 return ( <div> <ul> <li><Link to="/users">ユーザー一覧</Link></li> <li><Link to="/about">このサンプルについて</Link></li> </ul> <div> {this.props.children && React.cloneElement(this.props.children, { users: this.state.users })} </div> </div> ); } }); // Router や Route も React コンポーネント ReactDOM.render(( <Router> <Route path="/" component={MyApp}> <IndexRoute component={Users}/> <Route path="users" component={Users}/> <Route path="users/:id" component={UserDetail}/> <Route path="about" component={About}/> </Route> </Router> ), document.getElementById("content") );