Làm chủ TanStack Router: Tuyệt kỹ Routing Type-safe cho Developer React

Development tutorial - IT technology blog
Development tutorial - IT technology blog

Chấm dứt ác mộng 404 vì những lỗi typo ngớ ngẩn

Bạn đã bao giờ tốn cả tiếng đồng hồ debug chỉ để nhận ra mình gõ thừa một chữ ‘s’ trong navigate('/users/profile') chưa? Với React Router truyền thống, TypeScript hoàn toàn “mù tịt” trước các chuỗi URL. Kết quả là ứng dụng crash hoặc nhảy vào trang 404 trong sự ngỡ ngàng của người dùng, còn bạn thì chẳng nhận được cảnh báo nào khi code.

Trong một dự án thực tế với hơn 150 routes mà mình từng tham gia, việc refactor từ React Router sang TanStack Router đã giúp giảm 80% các lỗi liên quan đến điều hướng. Thay vì dựa vào trí nhớ, giờ đây IDE sẽ nhắc bài cho bạn từng ký tự. Nếu bạn đổi tên một route, toàn bộ codebase sẽ báo đỏ ngay lập tức. Đó mới chính là sự an tâm mà một lập trình viên chuyên nghiệp cần.

Lên bàn cân: React Router vs TanStack Router

Tại sao cộng đồng React lại đang xôn xao về TanStack Router đến vậy? Hãy nhìn vào sự khác biệt cốt lõi trong cách tiếp cận.

Lối mòn của React Router

Lối tư duy component-based (bọc <Route> trong <Routes>) từng rất thành công nhưng dần bộc lộ nhược điểm khi dự án phình to. Việc quản lý search params (như ?page=1&sort=desc) cực kỳ khổ sai. Bạn phải tự lấy string từ URL, ép kiểu thủ công và cầu nguyện rằng dữ liệu đó không bị null hay sai định dạng.

Tư duy hiện đại của TanStack Router

TanStack Router ưu tiên Type-safety tuyệt đối. Nó ép bạn định nghĩa cấu trúc route tree chặt chẽ ngay từ đầu. Khi dùng component <Link>, bạn chỉ việc nhấn Ctrl + Space, IDE sẽ hiển thị danh sách route chính xác 100%. Không còn chuyện gõ nhầm, không còn chuyện đoán mò.

Những lý do khiến TanStack Router trở thành “vua” routing mới

Mình quyết định chuyển hẳn sang hệ sinh thái của Tanner Linsley (cha đẻ TanStack Query) vì 3 điểm cộng đắt giá sau:

  • Kiểm soát TypeScript toàn diện: Mọi thứ từ path, params đến search params đều được định nghĩa kiểu dữ liệu rõ ràng.
  • Validate Search Params chuyên nghiệp: Bạn có thể dùng Zod để ép kiểu cho URL. Ví dụ: tham số page bắt buộc phải là số và mặc định là 1. Nếu user cố tình gõ page=abc, router sẽ tự động xử lý hoặc đưa về giá trị an toàn.
  • Xử lý Data Loading cực mượt: TanStack Router giúp loại bỏ tình trạng “Waterfall” (linh kiện render xong mới fetch data). Nó tải dữ liệu song song khi route đang load, giúp giảm thời gian chờ (LCP) xuống đáng kể.

Triển khai thực tế: Từ lý thuyết đến code chạy

Hãy cùng bắt tay vào xây dựng một cấu trúc routing chuẩn chỉnh, đủ sức gánh vác các dự án quy mô lớn.

1. Khởi tạo dự án

Mở terminal và thêm thư viện vào project của bạn:

npm install @tanstack/react-router zod
# Zod sẽ giúp chúng ta validate search params cực kỳ bá đạo

2. Xây dựng Route Tree

Chúng ta sẽ tạo file src/routes/root.tsx. Đây là xương sống của toàn bộ ứng dụng.

import { createRootRoute, Link, Outlet } from '@tanstack/react-router';
import { TanStackRouterDevtools } from '@tanstack/router-devtools';

export const routeTree = createRootRoute({
  component: () => (
    <div className="min-h-screen bg-gray-50">
      <nav className="p-4 border-b bg-white flex gap-4">
        <Link to="/" className="[&.active]:text-blue-600 [&.active]:font-bold">Trang chủ</Link>
        <Link to="/products" className="[&.active]:text-blue-600 [&.active]:font-bold">Sản phẩm</Link>
      </nav>
      <main className="p-6">
        <Outlet />
      </main>
      <TanStackRouterDevtools />
    </div>
  ),
});

3. Quản lý Search Params như một chuyên gia

Hãy tưởng tượng bạn đang làm trang danh sách sản phẩm. Việc lọc theo pagecategory chưa bao giờ dễ dàng hơn thế nhờ sự kết hợp với Zod.

import { createRoute } from '@tanstack/react-router';
import { z } from 'zod';

const productSearchSchema = z.object({
  page: z.number().fallback(1),
  q: z.string().optional(),
});

export const productsRoute = createRoute({
  getParentRoute: () => routeTree,
  path: 'products',
  validateSearch: (search) => productSearchSchema.parse(search),
  component: ProductsPage,
});

function ProductsPage() {
  const { page, q } = productsRoute.useSearch();
  return (
    <div>
      <h1>Kết quả tìm kiếm cho: {q || 'Tất cả'}</h1>
      <p>Đang ở trang: {page}</p>
    </div>
  );
}

Kinh nghiệm “xương máu” khi triển khai

Đừng bao giờ bỏ qua errorComponent. Trong môi trường thực tế, API có thể chết bất cứ lúc nào. Thay vì để người dùng đối mặt với màn hình trắng xóa vô hồn, hãy thiết kế một UI thông báo lỗi tử tế ngay tại route đó. Điều này giúp tăng trải nghiệm người dùng (UX) lên rất nhiều.

Một mẹo nhỏ cho các dự án lớn: Bạn không cần phải đập đi xây lại toàn bộ trong một ngày. Hãy thử áp dụng TanStack Router cho các module mới trước. Khi đã thấy được sự tiện lợi của nó, việc migration các phần còn lại sẽ trở nên đầy hứng khởi thay vì là gánh nặng.

Lời kết

Dù rào cản ban đầu về TypeScript có vẻ hơi cao, nhưng TanStack Router thực sự là một khoản đầu tư xứng đáng. Nó không chỉ giúp code sạch hơn mà còn bảo vệ bạn khỏi hàng tá lỗi runtime ngớ ngẩn. Nếu bạn muốn xây dựng những ứng dụng React bền vững và dễ bảo trì, hãy thử cài đặt nó ngay hôm nay.

Share: