• Trang chủ
  • Bài viết
    CodeSchool - Make coding great againCodeSchool - Make coding great again
    • Trang chủ
    • Bài viết

      Front-end

      • Home
      • Blog
      • Front-end
      • Routing với webapp React: Không dùng và có dùng thư viện

      Routing với webapp React: Không dùng và có dùng thư viện

      • Date 12/07/2020

      React là một thư viện JavaScript ở Front-end nên khi nói đến routing, chúng ta phải hiểu rằng đây là client-side routing.

      • Phân biệt kỹ thuật routing tại client-side và server-side

      Routing trong React là việc lựa chọn component nào nên được hiển thị, tạo cho người dùng cảm giác họ đang “di chuyển” giữa các trang giao diện. Mặc dù chúng ta có thể tự viết cấu trúc render có điều kiện kèm với History API để làm điều này nhưng trong thực tế người ta thường xài thư viện react-router với nhiều chức năng routing đa dạng hơn.

      Thử tự code chức năng routing

      Trước khi học cách dùng thư viện, chúng ta hãy thử tự viết chức năng routing để hiểu về nền tảng một chút. Hãy cùng xem ví dụ nhỏ dưới đây:

      Hãy bắt đầu từ file App.js:

      • Component <RoutingProvider> ở dòng 15 là một Context để các Route truy cập dữ liệu dùng chung.
      • Các component <RouteLink> từ dòng 20 đến 22 dùng để thực hiện client-side routing, nó có các cơ chế ngăn không cho trình duyệt gọi lên server để thực hiện server-side routing.
      • Các component <Route> từ dòng 25 đến 33 làm nhiệm vụ so khớp (match) để đưa ra quyết định có nên hiển thị nhánh con của nó hay không.

      Bây giờ hãy chuyển qua file router.js:

      • Component <RouteLink> xử lý sự kiện click vào link như sau (dòng 31 đến 33):
        • event.preventDefault() bảo trình duyệt đừng làm gì hết, để tao tự xử.
        • Hàm navigate() thêm một dòng vào history để hỗ trợ di chuyển tới lui bằng nút Back và Forward trên trình duyệt.
        • Hàm reRoute() chỉ là một mánh nhỏ, ép component <RoutingProvider> phải render lại toàn bộ app, khiến cho các component Route ở bên trong phải tiến hành chọn lựa lại giao diện cần hiển thị.
      • Component <Route> cũng đơn giản không kém, nó chỉ đơn giản là so khớp prop path của nó với phần path trong URL của trình duyệt để quyết định xem có nên hiển thị children của nó hay không.
        • currentPath.match(new RegExp(path + '(?:\\/|$)'))so khớp bằng biểu thức chính quy (regular expression), đảm bảo path “/tech” không khớp với path “/tech-support”.
      • Dòng 64 window.addEventListener('popstate', reRender) lắng nghe sự kiện người dùng nhấn nút Back và Forward trên trình duyệt web để thực hiện lại việc routing.
        • Code nhúng trong IDE online không hoạt động đúng với nút Back và Forward. Hãy mở link sau ở một tab mới https://71rbj.csb.app/ để chạy thử ví dụ này.

      Những chức năng sau đây cần trong thực tế nhưng tự code thì rất mất thời gian:

      • Tô sáng menu item tương ứng với trang hiện hành.
      • So khớp với wildcard *, + hay ?.Ví dụ route /tech* sẽ khớp với URL path “/tech”, “/techlist”, “/tech-support”; trong khi đó route /tech+ chỉ khớp với “/techlist” và “/tech-support”.
      • Tham số route (route parameter). Ví dụ route /articles/:pageIndex/:pageSize sẽ khớp với URL path “/articles/2/50”, đồng thời component bên trong route sẽ nhận được props chứa object { pageIndex: 2, pageSize: 50 }.
      • Route lồng nhau (nesting routes).
      • Chuyển đổi qua lại giữa hash-based và history-based routing.
      • v.v. và v.v.

      Hướng dẫn sử dụng react-router

      react-router không phải là thư viện duy nhất, cũng không cùng nhà phát hành với React nhưng nó phổ biến nhất trong cộng đồng lập trình viên React. Thư viện này chỉ cung cấp những logic xử lý cơ chế routing, ứng dụng React Web cần cài đặt thư viện react-router-dom còn ứng dụng di động React Native cần cài đặt react-router-native để tích hợp sâu hơn các chức năng routing. Cả hai thư viện này đều có dependency là react-router nên chỉ cần cài đặt một trong hai thư viện này thì cũng tự có react-router luôn.

      Bây giờ chúng ta hãy cài đặt thư viện react-router-dom (npm install react-router-dom hoặc yarn add react-router-dom) rồi sửa code của ví dụ ở trên một chút:

      Như vậy về chức năng ở tầng giao diện hầu như không thay đổi gì hết, kể cả nút Back và Forward, điểm khác biệt duy nhất là khi refresh hoặc copy-paste URL thì các bạn sẽ thấy menu item của trang hiện hành được tô sáng.

      Các loại Router

      Mỗi Router trong thư viện react-router-dom đại diện cho mỗi cơ chế routing khác nhau, các bạn có thể sửa dòng số 3 trong file App.js để thử nghiệm mỗi loại. Sau khi sửa và save code xong, hãy truy cập trực tiếp trang này để chức năng Back/Forward chạy đúng https://1ie1x.csb.app/.

      BrowserRouter

      Router này sử dụng History API giúp cho URL trong ô địa chỉ trình duyệt trông rất tự nhiên. Đây là loại Router phổ biến và khuyến khích các bạn nên xài, trừ phi yêu cầu của dự án bắt phải hỗ trợ các trình duyệt web cũ không hỗ trợ History API.

      HashRouter

      Đây là cơ chế routing dựa trên URL fragment (còn gọi là phần hash), tức là phần text nằm sau ký tự # của URL. Ưu điểm của nó là chạy được trên mọi loại trình duyệt, thậm chí hỗ trợ luôn nút Back và Forward.

      MemoryRouter

      Là cơ chế mà react-router sẽ tự quản lý trạng thái routing trong bộ nhớ chứ không phụ thuộc vào URL của trình duyệt. Cơ chế routing này đã từng phổ biến trong quá khứ, khi người ta chưa sáng tạo ra ý tưởng routing bằng URL hash. Ngày nay loại router này phù hợp cho các ứng dụng React không chạy trên trình duyệt web, ví dụ như React Native.

      Component <Route>

      Hiển thị component theo route

      Component này làm nhiệm vụ so khớp và ra quyết định có nên hiển thị component mà nó đại diện hay không, có 3 cách để gắn một component vào <Route>

      Dùng prop component nhận vào một React ElementType (kiểu của PropTypes), ví dụ <Route component={HomePage} path="..." />, nếu route được so khớp, component HomePage sẽ được hiển thị bằng hàm React.createElement.

      • Cấu tạo của một component trong React và cách tạo ra nó

      Dùng prop render nhận vào một function, function này phải trả về một React Node, ví dụ <Route render={(props) => <HomePage layout="compact" />} path="..." />. Cách này hữu dụng khi cần cấu hình nâng cao cho component.

      Dùng nhánh con, với cách này component bên trong luôn được React render, nhưng nếu route không so khớp thì nó không được gắn vào DOM để hiển thị lên giao diện.

      <Route path="...">
         <Homepage layout="full-fledged" />
      </Route>

      Quy tắc so khớp

      Với prop exact, route phải khớp đến từng ký tự mới với URL path thì mới được tính. Prop này phổ biến trong đa số trường hợp.

      Route path location.pathname exact khớp?
      /one/two /one/two true có
      /one /one/two true không
      /one /one/two false có

      Với prop sensitive, route phải khớp có phân biệt chữ hoa chữ thường (case-sensitive). Prop này ít được dùng trong thực tế.

      Route path location.pathname sensitive khớp?
      /one /one true có
      /One /one true không
      /One /one false có

      Component <Switch>

      Vì quá quen thuộc với server-side routing nên nhiều người vẫn tâm niệm rằng routing nghĩa là “chuyển trang”, thật ra với client-side routing, một phần tác dụng đúng là đem lại cảm giác “chuyển trang” cho người dùng, nhưng bản chất của nó là hiển thị component có điều kiện.

      Khi bọc những định nghĩa <Route> bên trong component <Switch>, chỉ có duy nhất một <Route> được hiển thị nếu nó so khớp, những <Route> còn lại sẽ bị bỏ qua (xét theo thứ tự từ trên xuống). Trong code ví dụ, chúng ta đã lợi dụng đặc tính này của <Switch> để hiển thị thông báo “ROUTE NOT FOUND” khi không có route nào ở trên được so khớp.

      Chúng ta có thể có những <Route> nằm ngoài <Switch>, tất cả những <Route> này đều sẽ được xử lý và sẽ có nhiều hơn một <Route> được hiển thị miễn là chúng so khớp.

      <Switch>
         {/* Cả 2 route đều khớp với path "/tech/articles", nhưng chỉ có route ở trên được hiển thị */}
         <Router path="/tech" />
         <Router path="/tech/articles" />
      </Switch>
      {/* Cả 2 route đều khớp với path "/course/mern" và đều được hiển thị */}
      <Router path="/course" />
      <Router path="/course/mern" />

      Component <Link> và <NavLink>

      Cả hai component này đều hiển thị thẻ <a> và bắt sự kiện onClick, ngăn không cho trình duyệt tự ý tải trang web mới. Component <NavLink> về cơ bản giống với <Link>, chỉ thêm một chức năng là so sánh URL của trình duyệt với giá trị href của thẻ <a>, nếu chúng khớp với nhau thì sẽ thêm một CSS class vào thẻ này. Mặc định class tên “active”, nhưng chúng ta có thể đổi tên khác qua prop activeClassName.

      Facebook Comments

      Tag:react

      • Share:
      author avatar
      CodeSchool trainer

      Previous post

      Phân biệt kỹ thuật routing tại client-side và server-side
      12/07/2020

      You may also like

      Các thủ thuật với JSX trong React (phần 1)
      2 July, 2020
      Cấu tạo của một component trong React và cách tạo ra nó
      1 July, 2020
      Giới thiệu cú pháp JSX khi lập trình webapp với React
      1 July, 2020

      Tìm kiếm

      Bài viết mới

      Routing với webapp React: Không dùng và có dùng thư viện
      12Jul2020
      Phân biệt kỹ thuật routing tại client-side và server-side
      11Jul2020
      Các thủ thuật với JSX trong React (phần 1)
      02Jul2020

      Giao lưu Facebook

      Facebook Pagelike Widget

      Giáo trình và bài viết được biên soạn và biên dịch bởi CodeSchool VN, bảo lưu mọi quyền.

      • Privacy
      • Terms
      • Sitemap