ReactJS: Cách xử lý định tuyến (route) trong ứng dụng React với React Router

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Giới thiệu

Trong Reactbộ định tuyến (router) giúp tạo và điều hướng giữa các URL khác nhau tạo nên ứng dụng web của bạn. Chúng cho phép người dùng của bạn di chuyển giữa các component của ứng dụng trong khi vẫn duy trì trạng thái người dùng và có thể cung cấp các URL duy nhất cho các component này để giúp chúng dễ chia sẻ hơn. Với router, bạn có thể cải thiện trải nghiệm người dùng của ứng dụng bằng cách đơn giản hóa việc điều hướng trang web.

React Router là một trong những framework định tuyến phổ biến nhất cho React. Thư viện được thiết kế với các thành phần trực quan để cho phép bạn xây dựng một hệ thống định tuyến khai báo cho ứng dụng của mình. Điều này có nghĩa là bạn có thể khai báo chính xác component của bạn với một route nhất định. Với việc khai báo định tuyến, bạn có thể tạo các route trực quan mà người dùng có thể đọc được, giúp quản lý kiến ​​trúc ứng dụng của bạn dễ dàng hơn.

Trong bài hướng dẫn này, bạn sẽ cài đặt và cấu hình Bộ định tuyến React, xây dựng một tập hợp các route và kết nối với chúng bằng cách sử dụng compnent <Link>. Bạn cũng sẽ xây dựng các route động thu thập dữ liệu từ một URL mà bạn có thể truy cập trong component của mình. Cuối cùng, bạn sẽ sử dụng Hook để truy cập dữ liệu và các thông tin định tuyến khác và tạo các route lồng nhau nằm bên trong các component được các route cha hiển thị.

Đến cuối hướng dẫn này, bạn sẽ có thể thêm các route vào bất kỳ dự án React nào và đọc thông tin từ các route của mình để bạn có thể tạo các component linh hoạt phản hồi dữ liệu URL.

Bước 1 - Tạo một dự án trống

Trong bước này, bạn sẽ tạo một dự án mới bằng Create React App. Sau đó, bạn sẽ xóa dự án mẫu và các tệp liên quan được cài đặt khi bạn khởi động dự án. Cuối cùng, bạn sẽ tạo một cấu trúc tệp đơn giản để tổ chức các component của mình. Điều này sẽ cung cấp cho bạn một cơ sở vững chắc để xây dựng ứng dụng mẫu của hướng dẫn này để tạo style trong bước tiếp theo.

Để bắt đầu, hãy thực hiện một dự án mới. Bạn mở terminal và chạy tập lệnh sau để cài đặt một dự án mới bằng cách sử dụng create-react-app:

npx create-react-app router-tutorial

Sau khi dự án kết thúc, hãy thay đổi vào thư mục:

cd router-tutorial

Khởi động dự án với lệnh:

npm start
Bạn sẽ nhận được một máy chủ cục bộ đang chạy. Nếu dự án không mở trong cửa sổ trình duyệt, bạn có thể mở nó bằng http://localhost:3000/. Nếu bạn đang chạy điều này từ một máy chủ từ xa, địa chỉ sẽ là .http://your_domain:3000

Trình duyệt của bạn sẽ tải với một ứng dụng React đơn giản được bao gồm như một phần của Create React App:

Dự án mẫu React

Bạn sẽ xây dựng một tập hợp các component tùy chỉnh hoàn toàn mới, vì vậy bạn sẽ cần bắt đầu bằng cách xóa một số mã soạn sẵn để bạn có thể có một dự án trống.

Để bắt đầu, hãy mở component src/App.js. Đây là component gốc được đưa vào trang. Tất cả các component sẽ bắt đầu từ đây. Bạn sửa lại file để trong đó chỉ còn chứa như sau:

import './App.css';

function App() {
  return <></>;
}

export default App;

Mở một terminal khác và thực hiện thao tác xóa file logo.svg:

rm src/logo.svg

Tạo thư mục components:

mkdir src/components

Tạo thư mục App:

mkdir src/components/App

Di chuyển các file App.* vào thư mục App:

mv src/App.* src/components/App

Mở file index.js và chỉnh sửa:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App/App';
import * as serviceWorker from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

Lưu file lại và quay lại trang web ta được một trang web trống.

màn hình trống trong chrome

Bây giờ bạn đã hoàn thành dự án Tạo ứng dụng React mẫu, hãy tạo một cấu trúc tệp đơn giản. Điều này sẽ giúp bạn giữ cho các component của bạn cô lập và độc lập.

Tạo một thư mục được gọi components trong thư mục src, components sẽ là nơi chứa tất cả các component tùy chỉnh của bạn.

Bước 2 - Cài đặt Bộ định tuyến React

Trong bước này, bạn sẽ cài đặt React Router vào dự án cơ sở của mình. Trong dự án này, bạn sẽ tạo một trang web nhỏ về các loài động vật có vú ở biển. Mỗi động vật có vú sẽ cần một component riêng biệt mà bạn sẽ kết xuất với bộ định tuyến. Sau khi cài đặt thư viện, bạn sẽ tạo một loạt các component cho mỗi động vật có vú. Đến cuối bước này, bạn sẽ có nền tảng để hiển thị các loài động vật có vú khác nhau dựa trên route.

Để bắt đầu, hãy cài đặt gói React Router. Có hai phiên bản khác nhau: phiên bản web và phiên bản gốc để sử dụng với React Native. Bạn sẽ cài đặt phiên bản web.

Trong thiết bị đầu cuối của bạn, sử dụng npm để cài đặt gói:

npm install react-router-dom

Gói sẽ được cài đặt và bạn sẽ nhận được một thông báo dạng như thông báo dưới khi quá trình cài đặt hoàn tất:

added 15 packages, and audited 2002 packages in 14s

151 packages are looking for funding
  run `npm fund` for details

10 moderate severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

Bây giờ bạn đã cài đặt gói. Trong phần còn lại của bước này, bạn sẽ tạo một loạt các component mà mỗi component sẽ có một route duy nhất.

Để bắt đầu, hãy tạo một thư mục cho ba loài động vật có vú khác nhau: manatee (lợn biển), narwhal (kỳ lân biển) và và whale (cá voi). Chạy các lệnh sau:

mkdir src/components/Manatee
mkdir src/components/Narwhal
mkdir src/components/Whale

Tiếp theo, tạo một component cho mỗi con vật. Trước tiên ta thêm một thẻ <h2> cho mỗi động vật có vú. Trong một ứng dụng đầy đủ, các component con có thể phức tạp. Chúng thậm chí còn có thể import và render các component con của riêng chúng. Đối với hướng dẫn này, bạn sẽ chỉ hiển thị thẻ <h2>.

Bắt đầu với component manatee. Tạo và mở file Manatee.js ra, sau đó thêm một component cơ bản:

export default function Manatee() {
  return <h2>Manatee</h2>;
}

Lưu file lại.

Tiếp theo, tạo một component cho narwhal. Thêm component cơ bản tương tự như trên, thay đổi nội dung trong <h2> thành Narwhal:

export default function Narwhal() {
  return <h2>Narwhal</h2>;
}

Lưu file lại.

Cuối cùng, tạo một component cho whale:

export default function Whale() {
  return <h2>Whale</h2>;
}

Lưu file lại.

Trong bước tiếp theo, bạn sẽ bắt đầu kết nối các route; bây giờ, hãy hiển thị component cơ bản trong ứng dụng của bạn.

Mở App.js ra, thêm một thẻ <h1> trong đó chứa tên của trang web (Marine Mammals) bên trong một thẻ <div> với className là wrapper. Đây sẽ là một mẫu (template) vì thẻ <div> và <h1> sẽ hiển thị trên mọi trang. Trong các ứng dụng đầy đủ, bạn có thể thêm thanh điều hướng hoặc header mà bạn muốn trên mọi trang.

Thêm các dòng được đánh dấu sau vào file:

import './App.css';
function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
    </div>
  );
}

export default App;

Tiếp theo, import Manatee và hiển thị bên trong <div>. Điều này sẽ hoạt động như một trình giữ chỗ cho đến khi bạn thêm các route khác:

import React from 'react';
import './App.css';

import Manatee from '../Manatee/Manatee';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <Manatee />
    </div>
  );
}

export default App;

Lưu file lại.

Bây giờ bạn đã có tất cả các component, hãy thêm một số phần đệm (padding) để cung cấp cho ứng dụng một ít không gian.

Mở App.css ra, sau đó thay thế nội dung với đoạn mã sau đây (bổ sung thêm một padding 20px cho class .wrapper):

.wrapper {
    padding: 20px;
}

Lưu file lại và quay lại trang web, bạn sẽ thấy các thành phần cơ bản của bạn:

Động vật có vú biển

Bây giờ bạn có một component gốc cơ bản mà bạn sẽ sử dụng để hiển thị các component khác. Nếu bạn không có bộ định tuyến, bạn có thể hiển thị có điều kiện các component bằng Hook useState. Nhưng điều này sẽ không mang lại trải nghiệm tuyệt vời cho người dùng của bạn. Bất cứ khi nào người dùng làm mới trang, lựa chọn của người dùng sẽ biến mất. Hơn nữa, họ sẽ không thể đánh dấu trang hoặc chia sẻ các state cụ thể của ứng dụng. Một bộ định tuyến sẽ giải quyết tất cả những vấn đề này. Bộ định tuyến sẽ duy trì trạng thái người dùng và sẽ cung cấp cho người dùng một URL rõ ràng để họ có thể lưu hoặc gửi cho người khác.

Như vậy ở bước này, bạn đã cài đặt React Router và tạo các component cơ bản. Các component sẽ là các trang riêng lẻ mà bạn sẽ hiển thị theo route. Trong bước tiếp theo, bạn sẽ thêm các route và sử dụng component <Link> để tạo các siêu liên kết hiệu quả.

Bước 3 - Thêm route

Trong bước này, bạn sẽ tạo một bộ định tuyến cơ sở với các route riêng cho từng trang. Bạn sẽ sắp xếp các route của mình để đảm bảo rằng các component được hiển thị chính xác và bạn sẽ sử dụng component <Link> đó để thêm các siêu liên kết vào dự án của mình mà sẽ không kích hoạt làm mới trang.

Đến cuối bước này, bạn sẽ có một ứng dụng có điều hướng sẽ hiển thị các component của bạn theo route.

React Router là một framework định tuyến khai báo. Điều đó có nghĩa là bạn sẽ cấu hình các route sử dụng các component React tiêu chuẩn. Có một số lợi thế cho cách tiếp cận này. Đầu tiên, nó tuân theo bản chất giải mã tiêu chuẩn của mã React. Bạn không cần phải thêm nhiều mã trong các phương thức componentDidMount hoặc bên trong một Hook useEffect; các route của bạn là các component. Thứ hai, bạn có thể đặt các route bên trong một component một cách trực quan với các component khác đóng vai trò như một khuôn mẫu (template). Khi bạn đọc mã, bạn sẽ tìm thấy chính xác vị trí các component động sẽ phù hợp với các chế độ xem toàn cục như điều hướng hoặc chân trang.

Để bắt đầu thêm các route, hãy mở App.js ra, thẻ <h1> sẽ đóng vai trò là tiêu đề trang global. Vì bạn muốn nó xuất hiện trên mọi trang, hãy định cấu hình bộ định tuyến sau thẻ này.

Import BrowserRouterRoute và Switch từ react-router-domBrowserRouter sẽ là cấu hình cơ sở. Switch sẽ bao ngoài các route động và component Route sẽ định cấu hình các route cụ thể và bọc component sẽ hiển thị:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <Manatee />
    </div>
  );
}

export default App;

Thêm component BrowserRouter để tạo một bộ định tuyến cơ sở. Mọi thứ bên ngoài component này sẽ hiển thị trên mọi trang, vì vậy hãy đặt nó sau thẻ <h1>. Ngoài ra, nếu bạn có toàn bộ trang web context mà bạn muốn sử dụng hoặc một số store khác như Redux, hãy đặt các component đó bên ngoài bộ định tuyến. Điều này sẽ làm cho chúng có sẵn cho tất cả các component trên bất kỳ route nào:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <Manatee />
      </BrowserRouter>
    </div>
  );
}

export default App;

Tiếp theo, thêm component Switch bên trong BrowserRouter. Component này sẽ kích hoạt đúng route, giống như câu lệnh switch JavaScript. Bên trong Switch, thêm một component Route cho mỗi route. Trong trường hợp này, bạn sẽ muốn các route sau: /manataee/narwhal, và /whale. Component Route sẽ nhận path làm tham số và bao quanh một component con. Component con sẽ hiển thị khi route đang hoạt động.

Tạo một route cho đường dẫn / và hiển thị component Manatee:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <Switch>
          <Route path="/">
            <Manatee />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại và quay lại trang web, bạn sẽ tìm thấy thông tin cho component Manatee:

Lợn biển xuất hiện tại tuyến đường /

Nếu bạn thử một route khác chẳng hạn như http://localhost:3000/whale, bạn sẽ vẫn nhận kết quả là component Manatee:

Lợn biển trên / tuyến đường cá voi

Component Switch sẽ hiển thị route đầu tiên phù hợp với mẫu đó. Bất kỳ route nào cũng sẽ phù hợp với /, vì vậy nó sẽ hiển thị trên mọi trang. Điều đó cũng có nghĩa là thứ tự là quan trọng. Vì bộ định tuyến sẽ thoát ngay khi tìm thấy một điểm trùng khớp, nên luôn đặt một route cụ thể hơn ở trước một route ít cụ thể hơn. Nói cách khác, /whale sẽ ở trước / và /whale/beluga sẽ ở trước /whale.

Nếu bạn muốn route chỉ khớp với route như đã viết chứ không phải bất kỳ route con nào, bạn có thể thêm prop exact. Ví dụ, <Route exact path="/manatee"> sẽ khớp với /manatee, nhưng không khớp /manatee/african.

Cập nhật route cho component Manatee là /manatee, sau đó import các component còn lại và tạo một route cho từng component:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <Switch>
          <Route path="/manatee">
            <Manatee />
          </Route>
          <Route path="/narwhal">
            <Narwhal />
          </Route>
          <Route path="/whale">
            <Whale />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại và quay lại trang web, nếu bạn truy cập http://localhost:3000/, thì chỉ thẻ <h1> sẽ hiển thị, vì không có route nào phù hợp với bất kỳ component Route nào:

Không có thành phần nào trên /

Nếu bạn truy cập http://localhost:3000/whale, bạn sẽ tìm thấy component Whale:

Cá voi trên / tuyến đường cá voi

Bây giờ bạn đã có một số component, hãy tạo điều hướng để người dùng di chuyển giữa các trang.

Sử dụng phần tử <nav> để biểu thị rằng bạn đang tạo một phần điều hướng của trang. Sau đó, thêm một danh sách không có thứ tự (<ul>) với một mục danh sách (<li>) và một siêu liên kết (<a>) cho mỗi động vật có vú:

import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <nav>
        <ul>
          <li><a href="/manatee">Manatee</a></li>
          <li><a href="/narwhal">Narwhal</a></li>
          <li><a href="/whale">Whale</a></li>
        </ul>
      </nav>
      <BrowserRouter>
        ...
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại và quay lại trang web, nhưng bạn sẽ gặp vấn đề. Vì bạn đang sử dụng các link trình duyệt gốc— thẻ <a>—nên bạn sẽ nhận được hành vi mặc định của trình duyệt bất kỳ khi nào bạn nhấp vào một liên kết. Điều đó có nghĩa là bất kỳ khi nào bạn nhấp vào một liên kết, bạn sẽ kích hoạt làm mới toàn bộ trang.

Lưu ý rằng mạng sẽ tải lại tất cả các tệp JavaScript khi bạn nhấp vào một liên kết. Đó là một chi phí hiệu suất lớn cho người dùng của bạn.

Làm mới trình duyệt khi nhấp vào liên kết

Tại thời điểm này, bạn có thể thêm một trình xử lý sự kiện click trên mỗi liên kết và ngăn hành động mặc định. Nhưng bạn sẽ cần làm rất nhiều công việc. Thay vì điều đó, React Router có một component đặc biệt được gọi là Link sẽ xử lý công việc cho bạn. Nó sẽ tạo một thẻ liên kết, nhưng ngăn chặn hành vi của trình duyệt mặc định trong khi đẩy vị trí mới.

Trong App.js, import Link từ react-router-dom. Sau đó thay thế từng thẻ <a> bằng component Link. Bạn cũng sẽ cần thay đổi thuộc tính href thành prop to.

Cuối cùng, di chuyển thành phần <nav> vào bên trong BrowserRouter. Điều này đảm bảo rằng component Link được kiểm soát bởi react-router:

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <nav>
          <ul>
            <li><Link to="/manatee">Manatee</Link></li>
            <li><Link to="/narwhal">Narwhal</Link></li>
            <li><Link to="/whale">Whale</Link></li>
          </ul>
        </nav>
        <Switch>
          <Route path="/manatee">
            <Manatee />
          </Route>
          <Route path="/narwhal">
            <Narwhal />
          </Route>
          <Route path="/whale">
            <Whale />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại và quay lại trang web, khi bạn nhấp vào liên kết, trang sẽ không làm mới và trình duyệt sẽ không tải lại mã JavaScript:

Không làm mới khi nhấp vào liên kết

Như vậy trong bước này, bạn đã thêm React Router vào dự án hiện tại của mình. Bạn đã tạo mỗi route cho từng component và bạn đã thêm một navigation bằng cách sử dụng component Link để chuyển đổi giữa các route mà không cần làm mới trang.

Trong bước tiếp theo, bạn sẽ thêm các route phức tạp hơn để hiển thị các component khác nhau bằng cách sử dụng các tham số URL.

Bước 4 - Truy cập dữ liệu route bằng Hook

Trong bước này, bạn sẽ sử dụng các tham số và truy vấn URL để tạo các route đường động. Bạn sẽ học cách lấy thông tin từ các tham số tìm kiếm bằng Hook useLocation và cách đọc thông tin từ các URL động bằng Hook useParams.

Đến cuối bước này, bạn sẽ biết cách truy cập thông tin route bên trong các component của mình và cách bạn có thể sử dụng thông tin đó để tải động các component.

Giả sử bạn muốn thêm một cấp độ khác vào ứng dụng động vật có vú biển của mình. Có nhiều loại cá voi và bạn có thể hiển thị thông tin về từng loại. Bạn có hai lựa chọn về cách thực hiện điều này: Bạn có thể sử dụng route hiện tại và thêm một loại cá voi cụ thể với các tham số tìm kiếm, chẳng hạn như ?type=beluga. Bạn cũng có thể tạo một route mới bao gồm tên cụ thể sau URL cơ sở, chẳng hạn như /whale/beluga. Hướng dẫn này sẽ bắt đầu với các tham số tìm kiếm, vì chúng linh hoạt và có thể xử lý nhiều truy vấn khác nhau.

Đầu tiên, tạo các component mới cho các loài cá voi khác nhau.

Tạo file Beluga.js nằm trong thư mục Whale, và mở ra rồi đưa nội dung sau vào:

export default function Beluga() {
  return(
    <h3>Beluga</h3>
  );
}

Làm điều tương tự với việc tạo và mở file Blue.js ra và đưa vào nội dung sau:

export default function Blue() {
  return(
    <h3>Blue</h3>
  );
}

Lưu file lại.

Truyền thông tin bổ sung với các tham số tìm kiếm

Tiếp theo, bạn sẽ truyền thông tin cá voi làm tham số tìm kiếm. Điều này sẽ cho phép bạn truyền thông tin mà không cần tạo URL mới.

Mở file App.js ra để bạn có thể thêm các liên kết mới:

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <nav>
          <ul>
            <li><Link to="/manatee">Manatee</Link></li>
            <li><Link to="/narwhal">Narwhal</Link></li>
            <li><Link to="/whale">Whale</Link></li>
            <li><Link to="/whale?type=beluga">Beluga Whale</Link></li>
            <li><Link to="/whale?type=blue">Blue Whale</Link></li>
          </ul>
        </nav>
        <Switch>
          ...
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại.

Nếu bạn nhấp vào các liên kết, bạn sẽ vẫn thấy trang cá voi thông thường. Điều này cho thấy rằng route tiêu chuẩn vẫn hoạt động chính xác:

Bộ định tuyến Beluga với trang cá voi

Vì bạn đang hiển thị chính xác component Whale, bạn sẽ cần cập nhật component để kéo truy vấn tìm kiếm ra khỏi URL và sử dụng nó để hiển thị đúng component con.

Mở file Whale.js ra, đầu tiên, import các component Beluga và Blue. Tiếp theo, import một Hook được gọi là useLocation từ react-router-dom:

import { useLocation } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  return <h2>Whale</h2>;
}

Hook useLocation kéo thông tin vị trí từ trang của bạn. Điều này không phải là duy nhất đối với React Router. Đối tượng location là một đối tượng tiêu chuẩn trên tất cả các trình duyệt. Nếu bạn mở bảng điều khiển trình duyệt và nhập window.location, bạn sẽ nhận được một đối tượng có thông tin về URL của bạn.

Vị trí cửa sổ trong bảng điều khiển

Lưu ý rằng thông tin vị trí bao gồm search, nhưng cũng bao gồm các thông tin khác, chẳng hạn như pathname và đầy đủ href. Hook useLocation sẽ cung cấp thông tin này cho bạn. Bên trong Whale.js, hãy gọi Hook useLocation. Destructure kết quả để rút ra trường search. Đây sẽ là một chuỗi tham số, chẳng hạn như ?type=beluga:

import { useLocation } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  const { search } = useLocation();
  return <h2>Whale</h2>;
}

Có một số thư viện, chẳng hạn như query-string, có thể phân tích cú pháp tìm kiếm cho bạn và chuyển đổi nó thành một đối tượng dễ đọc và dễ cập nhật hơn. Trong ví dụ này, bạn có thể sử dụng biểu thức chính quy để lấy thông tin về type của cá voi.

Sử dụng phương thức .match trên chuỗi tìm kiếm để kéo ra typesearch.match(/type=(.*)/). Các dấu ngoặc đơn bên trong biểu thức chính quy sẽ bắt khớp vào một mảng kết quả. Mục đầu tiên trong mảng là sự tương thích đầy đủ: type=beluga. Mục thứ hai là thông tin từ các dấu ngoặc đơn: beluga.

Sử dụng dữ liệu từ phương thức .match để hiển thị đúng component con:

import { useLocation } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  const { search } = useLocation();
  const match = search.match(/type=(.*)/);
  const type = match?.[1];

  return (
    <>
      <h2>Whale</h2>
      {type === 'beluga' && <Beluga />}
      {type === 'blue' && <Blue />}
    </>
  );
}

Biểu tượng ?. được gọi là chuỗi tùy chọn. Nếu giá trị tồn tại, nó trả về giá trị. Nếu không, nó sẽ trả về undefined. Điều này sẽ bảo vệ component của bạn trong trường hợp tham số tìm kiếm trống.

Lưu file lại và quay lại trang web, bạn sẽ thấy trang web sẽ hiển thị những con cá voi khác nhau:

Các loài cá voi khác nhau với các thông số tìm kiếm

Truy cập các tham số URL

Các tham số tìm kiếm đã hoạt động, nhưng chúng không phải là giải pháp tốt nhất trong trường hợp này. Nói chung, bạn sẽ sử dụng các tham số tìm kiếm để tinh chỉnh một trang: chuyển đổi thông tin hoặc tải dữ liệu cụ thể. Trong trường hợp này, bạn không tinh chỉnh một trang; bạn đang tạo một trang tĩnh mới. May mắn thay, React Router cung cấp một cách để tạo các URL động bảo vệ dữ liệu biến đổi được gọi là Tham số URL.

Mở App.js ra, thay vì truyền thông tin cá voi dưới dạng tìm kiếm, bạn sẽ thêm nó trực tiếp vào chính URL. Điều đó có nghĩa là bạn sẽ di chuyển seach vào URL thay vì thêm nó vào sau một ?. Ví dụ, truy vấn /whale?type=blue bây giờ sẽ là /whale/blue:

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <nav>
          <ul>
            <li><Link to="/manatee">Manatee</Link></li>
            <li><Link to="/narwhal">Narwhal</Link></li>
            <li><Link to="/whale">Whale</Link></li>
            <li><Link to="/whale/beluga">Beluga Whale</Link></li>
            <li><Link to="/whale/blue">Blue Whale</Link></li>
          </ul>
        </nav>
        <Switch>
          <Route path="/manatee">
            <Manatee />
          </Route>
          <Route path="/narwhal">
            <Narwhal />
          </Route>
          <Route path="/whale">
            <Whale />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Bây giờ bạn cần tạo một route mới có thể nắm bắt cả hai /whale/beluga và /whale/blue. Bạn có thể thêm chúng theo cách thủ công, nhưng điều này sẽ không hiệu quả trong các tình huống mà bạn không biết trước tất cả các khả năng, chẳng hạn như khi bạn có danh sách người dùng hoặc dữ liệu động khác.

Thay vì tạo route cho từng đường dẫn, hãy thêm tham số URL vào đường dẫn hiện tại. Tham số URL là một từ khóa được mở đầu bằng dấu hai chấm. React Router sẽ sử dụng tham số như một ký tự đại diện và sẽ khớp với bất kỳ route nào có chứa mẫu đó.

Trong trường hợp này, hãy tạo một từ khóa là :type. Toàn bộ path sẽ thành /whale/:type. Điều này sẽ khớp với bất kỳ route nào bắt đầu bằng /whale và nó sẽ lưu thông tin biến bên trong một biến tham số được gọi là type. Route này sẽ không khớp với /whale, vì nó không chứa tham số bổ sung.

Bạn có thể thêm /whale dưới dạng một route sau route mới hoặc bạn có thể thêm nó trước route /whale/:type bằng từ khóa exact.

Thêm route mới /whale/:type và thêm thuộc tính exact vào route hiện tại:

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <nav>
          <ul>
            <li><Link to="/manatee">Manatee</Link></li>
            <li><Link to="/narwhal">Narwhal</Link></li>
            <li><Link to="/whale">Whale</Link></li>
            <li><Link to="/whale/beluga">Beluga Whale</Link></li>
            <li><Link to="/whale/blue">Blue Whale</Link></li>
          </ul>
        </nav>
        <Switch>
          <Route path="/manatee">
            <Manatee />
          </Route>
          <Route path="/narwhal">
            <Narwhal />
          </Route>
          <Route exact path="/whale">
            <Whale />
          </Route>
          <Route path="/whale/:type">
            <Whale />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại. Bây giờ bạn đang truyền thông tin mới, bạn cần truy cập nó và sử dụng thông tin để hiển thị các component động.

Mở Whale.js ra, import Hook useParams. Thao tác này sẽ kết nối với bộ định tuyến của bạn và kéo bất kỳ tham số URL nào vào một đối tượng. Destructure đối tượng để kéo ra trường type. Xóa mã để phân tích cú pháp search và sử dụng tham số để hiển thị có điều kiện các component con:

import { useParams } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  const { type } = useParams();

  return (
    <>
      <h2>Whale</h2>
      {type === 'beluga' && <Beluga />}
      {type === 'blue' && <Blue />}
    </>
  );
}

Lưu file lại và quay lại trang web, bạn sẽ có thể sử dụng các URL mới, chẳng hạn như http://localhost:3000/whale/beluga.

Tham số URL là một cách rõ ràng để truyền dữ liệu có điều kiện. Chúng không linh hoạt như các tham số tìm kiếm, có thể được kết hợp hoặc sắp xếp lại, nhưng chúng rõ ràng hơn và dễ dàng hơn cho các công cụ tìm kiếm lập chỉ mục.

Trong bước này, bạn đã truyền dữ liệu biến bằng cách sử dụng tham số tìm kiếm và tham số URL. Bạn cũng đã sử dụng các Hook là useLocation và useParams để kéo thông tin ra ngoài và kết xuất các component có điều kiện.

Nhưng có một vấn đề: Danh sách các route ngày càng dài và bạn bắt đầu nhận được các bản sao khá tương tự với các route như /whale và /whale/:type. React Router cho phép bạn phân chia các route con trực tiếp trong component, có nghĩa là bạn không cần phải có toàn bộ danh sách trong một component duy nhất. Trong bước tiếp theo, bạn sẽ hiển thị các route trực tiếp bên trong các component con.

Bước 5 - Các route lồng nhau

Các route có thể phát triển và trở nên phức tạp hơn. React Router sử dụng các route lồng nhau để hiển thị thông tin định tuyến cụ thể hơn bên trong các component con. Trong bước này, bạn sẽ sử dụng các route lồng nhau và thêm các route trong các component khác nhau. Đến cuối bước này, bạn sẽ có các tùy chọn khác nhau để hiển thị thông tin của mình.

Trong bước cuối cùng, bạn đã thêm các route bên trong App.js. Điều này có một số ưu điểm: Nó giữ tất cả các route ở một nơi, về cơ bản là tạo sơ đồ trang web cho ứng dụng của bạn. Nhưng nó có thể dễ dàng phát triển và khó đọc và khó bảo trì. Các route lồng nhau nhóm thông tin định tuyến của bạn trực tiếp trong các component sẽ hiển thị các component khác, mang lại cho bạn khả năng tạo các mẫu nhỏ trong toàn bộ ứng dụng của mình.

Mở App.js ra, loại bỏ route /whale/:type và loại bỏ prop exact để bạn chỉ có một route whale:

import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';
import './App.css';

import Manatee from '../Manatee/Manatee';
import Narwhal from '../Narwhal/Narwhal';
import Whale from '../Whale/Whale';

function App() {
  return (
    <div className="wrapper">
      <h1>Marine Mammals</h1>
      <BrowserRouter>
        <nav>
          <ul>
            <li><Link to="/manatee">Manatee</Link></li>
            <li><Link to="/narwhal">Narwhal</Link></li>
            <li><Link to="/whale">Whale</Link></li>
            <li><Link to="/whale/beluga">Beluga Whale</Link></li>
            <li><Link to="/whale/blue">Blue Whale</Link></li>
          </ul>
        </nav>
        <Switch>
          <Route path="/manatee">
            <Manatee />
          </Route>
          <Route path="/narwhal">
            <Narwhal />
          </Route>
          <Route path="/whale">
            <Whale />
          </Route>
        </Switch>
      </BrowserRouter>
    </div>
  );
}

export default App;

Lưu file lại.

Tiếp theo, mở Whale.js ra. Đây là nơi bạn sẽ thêm route lồng nhau. Bạn sẽ cần phải làm hai điều. Đầu tiên, lấy đường dẫn hiện tại bằng Hook useRouteMatch. Tiếp theo, kết xuất <Switch> mới và các component <Route> để hiển thị các component một cách chính xác.

Import useRouteMatch. Điều này sẽ trả về một đối tượng có chứa path và url. Destructure đối tượng để lấy path. Bạn sẽ sử dụng điều này làm cơ sở cho các route mới của mình:

import { useRouteMatch } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  const { path } = useRouteMatch();

  return (
    <>
      <h2>Whale</h2>
      {type === 'beluga' && <Beluga />}
      {type === 'blue' && <Blue />}
    </>
  );
}

Tiếp theo, import Switch và Route để bạn có thể thêm các route mới. Các route mới của bạn sẽ giống như khi bạn đã thực hiện trong App.js, nhưng bạn không cần phải bọc chúng lại bằng BrowserRouter. Thêm các route mới, nhưng thêm tiền tố route bằng path. Component mới sẽ hiển thị chính xác nơi bạn đặt chúng, vì vậy hãy thêm các route mới sau <h2>:

import { Switch, Route, useRouteMatch } from 'react-router-dom';
import Beluga from './Beluga';
import Blue from './Blue';

export default function Whale() {
  const { path } = useRouteMatch();
  return (
    <>
      <h2>Whale</h2>
      <Switch>
        <Route path={`${path}/beluga`}>
          <Beluga />
        </Route>
        <Route path={`${path}/blue`}>
          <Blue />
        </Route>
      </Switch>
    </>
  );
}

Lưu file lại và quay lại trang web, bạn sẽ có thể truy cập các route con.

Tham quan các tuyến đường dành cho trẻ em

Đây là một mã bổ sung nhỏ, nhưng nó giữ cho các route con nằm cùng với route cha của chúng. Không phải tất cả các dự án đều sử dụng các route lồng nhau: một số thích có một danh sách rõ ràng. Đó là vấn đề về sự ưu tiên và nhất quán của team. Chọn tùy chọn tốt nhất cho dự án của bạn và bạn luôn có thể cấu trúc lại sau.

Như vậy trong bước này, bạn đã thêm các route lồng nhau vào dự án của mình. Bạn đã kéo ra đường dẫn hiện tại bằng Hook useRouteMatch và thêm các đường dẫn mới trong một component để hiển thị các component mới bên trong một component cơ sở.

Phần kết luận

React Router là một phần quan trọng của bất kỳ dự án React nào. Khi bạn xây dựng các ứng dụng trang đơn, bạn sẽ sử dụng các route để tách ứng dụng của mình thành các phần có thể sử dụng được mà người dùng có thể truy cập dễ dàng và nhất quán.

Khi bạn bắt đầu tách các component của mình thành các route, bạn sẽ có thể tận dụng lợi thế của việc tách mã, duy trì trạng thái thông qua các tham số truy vấn và các công cụ khác để cải thiện trải nghiệm người dùng.

» Tiếp: Cách thêm xác thực đăng nhập vào ứng dụng React
« Trước: Cách quản lý state trong React với Redux
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!