Tiếng Việt

Khám phá các mẫu điều hướng thiết yếu với React Router v6. Tìm hiểu về định tuyến khai báo, định tuyến động, điều hướng theo lập trình, định tuyến lồng nhau và các chiến lược tải dữ liệu để xây dựng ứng dụng web mạnh mẽ và thân thiện với người dùng.

React Router v6: Làm chủ các Mẫu Điều hướng cho Ứng dụng Web Hiện đại

React Router v6 là một thư viện định tuyến mạnh mẽ và linh hoạt cho các ứng dụng React. Nó cho phép bạn tạo ra các ứng dụng trang đơn (SPA) với trải nghiệm người dùng liền mạch bằng cách quản lý điều hướng mà không cần tải lại toàn bộ trang. Bài viết này sẽ đi sâu vào các mẫu điều hướng thiết yếu sử dụng React Router v6, cung cấp cho bạn kiến thức và ví dụ để xây dựng các ứng dụng web mạnh mẽ và thân thiện với người dùng.

Hiểu các Khái niệm Cốt lõi của React Router v6

Trước khi đi sâu vào các mẫu cụ thể, hãy cùng xem lại một số khái niệm cơ bản:

1. Định tuyến Khai báo với <Routes><Route>

Nền tảng của React Router v6 nằm ở định tuyến khai báo. Bạn định nghĩa các route của mình bằng cách sử dụng các component <Routes><Route>. Component <Routes> hoạt động như một vùng chứa cho các route của bạn, và component <Route> định nghĩa một route cụ thể và component sẽ được render khi route đó khớp với URL hiện tại.

Ví dụ: Cấu hình Route Cơ bản

Đây là một ví dụ cơ bản về cách thiết lập các route cho một ứng dụng đơn giản:


import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import About from "./pages/About";
import Contact from "./pages/Contact";

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

export default App;

Trong ví dụ này, chúng ta định nghĩa ba route:

Component BrowserRouter cho phép định tuyến dựa trên lịch sử trình duyệt. React Router sẽ so khớp URL hiện tại với các route đã định nghĩa và render component tương ứng.

2. Định tuyến Động với Tham số URL

Định tuyến động cho phép bạn tạo ra các route có thể xử lý các giá trị khác nhau trong URL. Điều này hữu ích để hiển thị nội dung dựa trên một định danh duy nhất, chẳng hạn như ID sản phẩm hoặc ID người dùng. React Router v6 sử dụng ký hiệu : để định nghĩa các tham số URL.

Ví dụ: Hiển thị Chi tiết Sản phẩm

Giả sử bạn có một ứng dụng thương mại điện tử và muốn hiển thị chi tiết cho mỗi sản phẩm dựa trên ID của nó. Bạn có thể định nghĩa một route động như sau:


import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";

function ProductDetails() {
  const { productId } = useParams();

  // Lấy chi tiết sản phẩm dựa trên productId
  // ...

  return (
    

Product Details

Product ID: {productId}

{/* Hiển thị chi tiết sản phẩm tại đây */}
); } function App() { return ( } /> ); } export default App;

Trong ví dụ này:

Ví dụ về Quốc tế hóa: Xử lý Mã Ngôn ngữ

Đối với một trang web đa ngôn ngữ, bạn có thể sử dụng một route động để xử lý các mã ngôn ngữ:


} />

Route này sẽ khớp với các URL như /en/about, /fr/about, và /es/about. Tham số lang sau đó có thể được sử dụng để tải các tài nguyên ngôn ngữ phù hợp.

3. Điều hướng theo Lập trình với useNavigate

Mặc dù định tuyến khai báo rất phù hợp cho các liên kết tĩnh, bạn thường cần điều hướng theo lập trình dựa trên hành động của người dùng hoặc logic ứng dụng. React Router v6 cung cấp hook useNavigate cho mục đích này. useNavigate trả về một hàm cho phép bạn điều hướng đến các route khác nhau.

Ví dụ: Chuyển hướng sau khi Gửi Biểu mẫu

Giả sử bạn có một biểu mẫu và muốn chuyển hướng người dùng đến trang thành công sau khi biểu mẫu được gửi thành công:


import { useNavigate } from "react-router-dom";

function MyForm() {
  const navigate = useNavigate();

  const handleSubmit = async (event) => {
    event.preventDefault();

    // Gửi dữ liệu biểu mẫu
    // ...

    // Chuyển hướng đến trang thành công sau khi gửi thành công
    navigate("/success");
  };

  return (
    
{/* Các trường của biểu mẫu */}
); } export default MyForm;

Trong ví dụ này:

Truyền State trong khi Điều hướng

Bạn cũng có thể truyền state cùng với việc điều hướng bằng cách sử dụng đối số thứ hai cho navigate:


navigate("/confirmation", { state: { orderId: "12345" } });

Điều này cho phép bạn truyền dữ liệu đến component đích, dữ liệu này có thể được truy cập bằng hook useLocation.

4. Định tuyến Lồng nhau và Bố cục

Định tuyến lồng nhau cho phép bạn tạo các cấu trúc định tuyến phân cấp, trong đó một route được lồng bên trong một route khác. Điều này hữu ích để tổ chức các ứng dụng phức tạp với nhiều cấp độ điều hướng. Nó giúp tạo ra các bố cục nơi một số yếu tố giao diện người dùng luôn hiện diện trong một phần của ứng dụng.

Ví dụ: Phần Hồ sơ Người dùng

Giả sử bạn có một phần hồ sơ người dùng với các route lồng nhau để hiển thị thông tin hồ sơ, cài đặt và đơn hàng của người dùng:


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function Profile() {
  return (
    

User Profile

  • Profile Information
  • Settings
  • Orders
} /> } /> } />
); } function ProfileInformation() { return

Profile Information Component

; } function Settings() { return

Settings Component

; } function Orders() { return

Orders Component

; } function App() { return ( } /> ); } export default App;

Trong ví dụ này:

Dấu * trong route cha là rất quan trọng; nó biểu thị rằng route cha sẽ khớp với bất kỳ đường dẫn con nào, cho phép các route lồng nhau được khớp đúng cách bên trong component Profile.

5. Xử lý Lỗi "Không Tìm thấy" (404)

Việc xử lý các trường hợp người dùng điều hướng đến một route không tồn tại là rất cần thiết. React Router v6 giúp việc này trở nên dễ dàng với một route bắt tất cả (catch-all).

Ví dụ: Triển khai trang 404


import { BrowserRouter, Routes, Route, Link } from "react-router-dom";

function NotFound() {
  return (
    

404 - Not Found

The page you are looking for does not exist.

Go back to home
); } function App() { return ( } /> } /> } /> ); }

Trong ví dụ này:

6. Các Chiến lược Tải Dữ liệu với React Router v6

React Router v6 không bao gồm các cơ chế tải dữ liệu tích hợp sẵn như phiên bản tiền nhiệm (React Router v5 với `useRouteMatch`). Tuy nhiên, nó cung cấp các công cụ để triển khai hiệu quả các chiến lược tải dữ liệu khác nhau.

Lựa chọn 1: Lấy Dữ liệu trong Components

Cách tiếp cận đơn giản nhất là lấy dữ liệu trực tiếp bên trong component render route đó. Bạn có thể sử dụng hook useEffect để lấy dữ liệu khi component được mount hoặc khi các tham số URL thay đổi.


import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";

function ProductDetails() {
  const { productId } = useParams();
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchProduct() {
      try {
        const response = await fetch(`/api/products/${productId}`);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        setProduct(data);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchProduct();
  }, [productId]);

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; if (!product) return

Product not found

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Cách tiếp cận này đơn giản nhưng có thể dẫn đến trùng lặp mã nếu bạn cần lấy dữ liệu trong nhiều component. Nó cũng kém hiệu quả hơn vì việc lấy dữ liệu chỉ bắt đầu sau khi component được mount.

Lựa chọn 2: Sử dụng Custom Hook để Lấy Dữ liệu

Để giảm trùng lặp mã, bạn có thể tạo một custom hook đóng gói logic lấy dữ liệu. Hook này sau đó có thể được tái sử dụng trong nhiều component.


import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchData() {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const json = await response.json();
        setData(json);
        setLoading(false);
      } catch (e) {
        setError(e);
        setLoading(false);
      }
    }

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

Sau đó, bạn có thể sử dụng hook này trong các component của mình:


import { useParams } from "react-router-dom";
import useFetch from "./useFetch";

function ProductDetails() {
  const { productId } = useParams();
  const { data: product, loading, error } = useFetch(`/api/products/${productId}`);

  if (loading) return 

Loading...

; if (error) return

Error: {error.message}

; if (!product) return

Product not found

; return (

{product.name}

{product.description}

); } export default ProductDetails;

Lựa chọn 3: Sử dụng Thư viện Định tuyến có Khả năng Tải Dữ liệu (TanStack Router, Remix)

Các thư viện như TanStack RouterRemix cung cấp các cơ chế tải dữ liệu tích hợp, tích hợp liền mạch với định tuyến. Các thư viện này thường cung cấp các tính năng như:

Sử dụng một thư viện như vậy có thể đơn giản hóa đáng kể việc tải dữ liệu và cải thiện hiệu suất, đặc biệt đối với các ứng dụng phức tạp.

Kết xuất phía Máy chủ (SSR) và Tạo Trang Tĩnh (SSG)

Để cải thiện SEO và hiệu suất tải ban đầu, hãy xem xét sử dụng SSR hoặc SSG với các framework như Next.js hoặc Gatsby. Các framework này cho phép bạn lấy dữ liệu trên máy chủ hoặc trong thời gian xây dựng và phục vụ HTML đã được render sẵn cho máy khách. Điều này loại bỏ nhu cầu máy khách phải lấy dữ liệu khi tải lần đầu, mang lại trải nghiệm nhanh hơn và thân thiện với SEO hơn.

7. Làm việc với các Loại Router Khác nhau

React Router v6 cung cấp các triển khai router khác nhau để phù hợp với nhiều môi trường và trường hợp sử dụng:

Hãy chọn loại router phù hợp nhất với yêu cầu và môi trường của ứng dụng của bạn.

Kết luận

React Router v6 cung cấp một giải pháp định tuyến toàn diện và linh hoạt cho các ứng dụng React. Bằng cách hiểu và áp dụng các mẫu điều hướng đã thảo luận trong bài viết này, bạn có thể xây dựng các ứng dụng web mạnh mẽ, thân thiện với người dùng và dễ bảo trì. Từ định tuyến khai báo với <Routes><Route> đến các route động với tham số URL, điều hướng theo lập trình với useNavigate, và các chiến lược tải dữ liệu hiệu quả, React Router v6 trao quyền cho bạn để tạo ra những trải nghiệm điều hướng liền mạch cho người dùng của mình. Hãy cân nhắc khám phá các thư viện định tuyến nâng cao và các framework SSR/SSG để có khả năng kiểm soát và tối ưu hóa hiệu suất tốt hơn nữa. Hãy nhớ điều chỉnh các mẫu này cho phù hợp với yêu cầu ứng dụng cụ thể của bạn và luôn ưu tiên trải nghiệm người dùng rõ ràng và trực quan.