Reactjs - Bài 14 - React router

Reactjs - router

[Update ngày 21/06/2016]
Nội dung bài viết bên dưới cách đây 1 năm, hiện tại react-router đã update rất nhiều, nên tôi khuyến khích các bạn hãy cập nhật nội dung về  react-router tại
https://github.com/reactjs/react-router-tutorial/tree/master/lessons

Tuy nhiên nội dung bên dưới vẫn có giá trị tham khảo, đặc biệt là khi có và không có react-router.

Goal

Giới thiệu react-router.

Giới thiệu

Nếu các bạn đã trải qua các bài viết từ bài đầu tiên đến giờ có lẽ bạn cũng đã nhận ra rằng React.js chỉ là thư viện để tạo các Component, nó không có Router.
react-router được dùng để giúp việc dẫn hướng UI đồng bộ với URL.
Để giúp các bạn hiểu rõ hơn react-router, chúng ta sẽ thử implement 2 tình huống như sau
- Without react-router
- With react-router
- Server rendering react-router
Cách này tôi dựa trên ý tưởng theo tài liệu của React Router nhưng được trình bày lại theo luồng source code demo từ những bài trước, cho nên nếu việc tham khảo trực tiếp thông qua tài liệu của React Router khiến bạn dễ hiểu hơn thì bạn nên tham khảo nó.
Ý tưởng demo như sau:
Chúng ta sẽ sử dụng source code Avatar list, và thêm trang detail cho từng Avatar. Có nghĩa là từ list Avatar, click vào link của từng Avatar thì nó chuyển sang trang Avatar detail của Avatar đó.

Without react-router

Thêm đoạn code xử lý load nội dung Avatar list hay Avatar Item theo route:
var App = React.createClass({
  render(){
    var Child;
    switch (this.props.route) {
      case 'avatars': Child = Avatars; break;
      case 'avatar': Child = Avatar; break;
      default: Child = Avatars;
    }
    return(
      <div>
        <Child />
      </div>
    )
  }
});

function render(){
  var route = window.location.hash.substr(1);
  React.render(<App route = {route}/>, document.body);
}
window.addEventListener('hashchange', render);
render();
App sẽ render các nội dung khác nhau tùy theo giá trị this.props.route. Nếu chỉ 2 trường hợp như trên thì còn khá là đơn giản nhưng trong trường hợp nhiều trang hơn, nhiều cấp cho route hơn thì vấn đề sẽ nhanh chóng trở nên phức tạp.
Source code minh họa:
https://github.com/phungnc/reactjs-tut-demo/tree/feature/route_without_react_router/route-without-react-router
Lưu ý: Vì tôi đã giới thiệu việc dùng browserify trong bài trước, nên từ bây giờ tôi sẽ dùng browserify cho việc require các module cần thiết. Cho bạn cần dùng câu lệnh sau để build file bundle.js
browserify -t reactify avatar.jsx > bundle.js

With react-router

Phần xử lý route sẽ trở thành:
var routes  = (
  <Route handler={App}>
    <DefaultRoute handler={Avatars} />
    <Route name="avatars" handler={Avatars} />
    <Route name="avatar" handler={Avatar} />
  </Route>
);

var App = React.createClass({
  render(){
    return(
      <div>
        <RouteHandler/>
      </div>
    )
  }
});
//Finally we need to listen to the url and render the application.
Router.run(routes, Router.HashLocation, function(Root) {
  React.render(<Root/>, document.body);
});
Nhớ là bạn cần ‘require’ react-router Router = require('react-router'); ở đầu file.
Source code:
https://github.com/phungnc/reactjs-tut-demo/tree/feature/route_with_react_router/route-with-react-router
Trong phần này, bạn cần đọc thêm các nội dung ở link này:
https://github.com/reactjs/react-router-tutorial/tree/master/lessons

Server-side rendering and react-router

React-router chẳng những có thể dùng ở phía client mà còn dùng được ngay cả khi render React App ở phía Server.
Nếu bạn hiểu sơ qua nguyên lý hoạt động React-router ở trên và đã đọc qua bài viết Server-side rendering thì việc modify lại code dùng React-router cho phía server sẽ không có vấn đề gì. Chỉ cần chú ý một chút là ở Sever chúng ta bundle up file browser.js
browserify -t reactify browser.js > bundle.js
Source code:
https://github.com/phungnc/reactjs-tut-demo/tree/feature/server_side_react_router/server-rendering-react-router