Tìm hiểu ReactJS Router với ví dụ tại phía Client

Xem thêm các chuyên mục:

1- React Router là gì?

React Router là một thư viện định tuyến (routing) tiêu chuẩn trong React. Nó giữ cho giao diện của ứng dụng đồng bộ với URL trên trình duyệt. React Router cho phép bạn định tuyến "luồng dữ liệu"(data flow) trong ứng dụng của bạn một cách rõ ràng. Nó tương đương với sự khẳng định, nếu bạn có URL này, nó sẽ tương đương với Route (tuyến đường) này, và giao diện sẽ thế này!
React Router thực sự có ích và được sử dụng rộng rãi trong các ứng dụng React tại phía Server hơn là các ứng dụng React tại phía Client. Cụ thể là React Router thường được sử dụng trong ứng dụng React trong môi trường NodeJS Server, nó cho phép bạn định nghĩa ra các URL động nhưng phù hợp với triết lý "Single Page Application" (Ứng dụng một trang) của React. Phát triển một ứng dụng React bạn cần viết nhiều Component nhưng chỉ cần duy nhất một tập tin để phục vụ người dùng đó là index.html (Cơ bản là thế).
React Router giúp bạn định nghĩa ra các URL động, và lựa chọn Component phù hợp để render trên trình duyệt người dùng ứng với từng URL.

<BrowserRouter> vs <HashRouter>

React Router cung cấp cho bạn 2 thành phần là <BrowserRouter> & <HashRouter>. Hai thành phần này khác nhau ở kiểu URL mà chúng sẽ tạo ra và đồng bộ.
// <BrowserRouter>
http://example.com/about
 
// <HashRouter>
http://example.com/#/about
 
<BrowserRouter> được sử dụng phổ biến hơn, nó sử dụng History API có trong HTML5 để theo dõi lịch sử bộ định tuyến của bạn. Trong khi đó <HashRouter> sử dụng hash của URL ( window.location.hash) để ghi nhớ mọi thứ. Nếu bạn có ý định hỗ trợ các trình duyệt cũ, hoặc ứng dụng React sử dụng Router ở phía client thì <HashRouter> là lựa chọn hợp lý.

<Route>

Thành phần <Route> định nghĩa một ánh xạ (mapping) giữa một URL và một Component. Điều đó có nghĩa là khi người dùng truy cập theo một URL trên trình duyệt, một Component tương ứng sẽ được render trên giao diện.
<BrowserRouter>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/topics" component={Topics}/>
</BrowserRouter>
 
 
<HashRouter>
  <Route exact path="/" component={Home}/>
  <Route path="/about" component={About}/>
  <Route path="/topics" component={Topics}/>
</HashRouter>
 
Thuộc tính exact được sử dụng trong <Route> để nói rằng <Route> này chỉ hoạt động nếu URL trên trình duyệt phù hợp tuyệt đối với giá trị của thuộc tính path của nó.

<BrowserRouter>
    ...
    <Route path="/about" component={About}/>
    ...
</BrowserRouter>


http://example.com/about                                         ==> OK Work!
http://example.com/about#somthing                       ==> OK Work!
http://example.com/about/something                       ==> OK Work!
http://example.com/about/a/b                                   ==> OK Work!

-------------------

http://example.com/something/about                        ==> Not Work!
http://example.com/something/about#something    ==> Not Work!
http://example.com/something/about/something      ==> Not Work!

<HashRouter>
    ...
    <Route path="/about" component={About}/>
    ...
</HashRouter>


http://example.com#/about                                        ==> OK Work!
http://example.com#/about/somthing                        ==> OK Work!

----------------

http://example.com/something                                  ==> Not Work!
http://example.com/something#/about                     ==> Not Work!

<BrowserRouter>
    ...
    <Route exact path="/about" component={About}/>
    ...
</BrowserRouter>



http://example.com/about                                        ==> OK Work!
http://example.com/about#somthing                      ==> OK Work!

-------------

http://example.com/about/something                      ==> Not Work!
http://example.com/about/a/b                                  ==> Not Work!

http://example.com/something/about                      ==> Not Work!
http://example.com/something/about#something  ==> Not Work!
http://example.com/something/about/something    ==> Not Work!

<HashRouter>
    ...
    <Route exact path="/about" component={About}/>
    ...
</HashRouter>


http://example.com#/about                                     ==> OK Work!

----------------

http://example.com#/about/somthing                    ==>  Not Work!
http://example.com/something                               ==>  Not Work!
http://example.com/something#/about                  ==>  Not Work!

Nếu bạn đang tìm một ví dụ về React Router tại phía Server ( NodeJS) các bài viết dưới đây có thể có ích cho bạn:

2- React Router tại phía Client

OK, Trong bài học này tôi sẽ hướng dẫn bạn tạo một ứng dụng React sử dụng React Router tại phía Client. Dưới đây là hình ảnh xem trước của ứng dụng.
Các thư viện cần thiết cho ứng dụng của bạn:
<!-- React & ReactDOM Libraries -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

<!-- React Router -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.min.js"></script>

<!-- Babel -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>

<!-- CSS -->
<link rel = "stylesheet" type = "text/css" href = "router-example.css" />
Nếu bạn muốn tìm kiếm một phiên bản thư viện mới hơn hãy truy cập vào link dưới đây:
hashrouter-example.css
.product {
   padding: 5px;
   margin-bottom: 15px;
   background-color: #ddd;
}

 .product-nav a {
   background-color: #ddd;
   margin: 5px;
   padding: 5px;
   text-decoration: none
 }

 .selected {
    color: red;
 }

 .route-place {
     margin-top: 10px;
     padding: 30px;
     height: 100%;
     border: 1px solid #ddd;
}
hashrouter-example.html
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>ReactJS Router</title>

      <!-- React & ReactDOM Libraries -->
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>

      <!-- React Router -->
      <script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.min.js"></script>

     <!-- Babel -->
      <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>

      <!-- CSS -->
      <link rel = "stylesheet" type = "text/css" href = "hashrouter-example.css" />

   </head>
   <body>
      <h3>Client Side ReactJS Router</h3>

      <div id="app"></div>

      <script src="hashrouter-example.jsx" type="text/babel"></script>
   </body>
</html>
hashrouter-example.jsx
// import {BrowserRouter,NavLink} from 'react-router-dom';
// const { HashRouter, NavLink, Route } = ReactRouterDOM;

// Component
class ProductShortInfo extends React.Component {
  render() {
    return (
      <div className="product">
        <h3>Samsung Galaxy S9</h3>
        <p>Price: $900</p>
      </div>
    );
  }
}

// Component
class ProductFeature extends React.Component {
  render() {
    return <h3>Some Features of Samsung Galaxy S9!</h3>;
  }
}

// Component
class ProductImages extends React.Component {
  render() {
    return <h3>Some Images of Samsung Galaxy S9</h3>;
  }
}

// Component
class ProductComments extends React.Component {
  render() {
    return <h3>Some Customer Comments</h3>;
  }
}

//
class Product extends React.Component {
  render() {
    return (
      <ReactRouterDOM.HashRouter>
        <div>
          <ProductShortInfo />

          <div className="product-nav">
            <ReactRouterDOM.NavLink exact to="/" activeClassName="selected">
              Feature
            </ReactRouterDOM.NavLink>

            <ReactRouterDOM.NavLink exact to="/images" activeClassName="selected">
              Images
            </ReactRouterDOM.NavLink>

            <ReactRouterDOM.NavLink to="/comments" activeClassName="selected">
              Comments
            </ReactRouterDOM.NavLink>
          </div>
          <div className="route-place">
            <ReactRouterDOM.Route exact path="/" component={ProductFeature} />
            <ReactRouterDOM.Route exact path="/images" component={ProductImages} />
            <ReactRouterDOM.Route path="/comments" component={ProductComments} />
          </div>
        </div>
      </ReactRouterDOM.HashRouter>
    );
  }
}
//
class App extends React.Component {
  render() {
    return <Product />;
  }
}

// Render
ReactDOM.render(<App />, document.querySelector("#app"));
Chú ý: Hai thành phần: <ReactRouterDOM.NavLink> & <ReactRouterDOM.Link> rất giống nhau về cách sử dụng, <ReactRouterDOM.NavLink> tốt hơn vì nó hỗ trợ thuộc tính activeClassName (Có ích trong ví dụ này).

Xem thêm các chuyên mục: