Sửa lỗi 'No routes matched location' trong React Router

beginner⚛️ React2026-03-25| React 18+, React Router v6 (react-router-dom 6.x), Node.js 18+, mọi hệ điều hành

Error Message

No routes matched location "/dashboard"
#react#react-router#routing#spa

Tình huống

Bạn điều hướng đến /dashboard — hoặc nhấp vào một <Link> trỏ đến đó — và màn hình trắng xóa. Không có component nào, không có error boundary, chỉ là trống rỗng. Console hiển thị:

No routes matched location "/dashboard"

React Router v6 đã quét toàn bộ <Route> trong block <Routes> của bạn nhưng không tìm thấy kết quả. Có năm nguyên nhân thường gặp. Hãy loại trừ từng cái một.

Quy trình debug

1. Kiểm tra cây route thực tế của bạn trông như thế nào

Mở component nơi bạn định nghĩa route và đọc từng ký tự trong path. Chỉ một chữ hoa cũng có thể phá vỡ mọi thứ:

// Sai — path là "Dashboard" (chữ D viết hoa)
<Route path="/Dashboard" element={<Dashboard />} />

// Link trỏ đến chữ thường
<Link to="/dashboard">Go</Link>

React Router phân biệt chữ hoa chữ thường trong path. /Dashboard/dashboard là hai route hoàn toàn khác nhau — nó sẽ không tự động xử lý việc khớp chúng.

2. Xác nhận route nằm bên trong

Một <Route> đặt bên ngoài component <Routes> sẽ bị bỏ qua một cách im lặng. Nó không báo lỗi, chỉ đơn giản là không làm gì cả:

// Sai — Route nằm ngoài Routes
<BrowserRouter>
  <Route path="/dashboard" element={<Dashboard />} />
</BrowserRouter>

// Đúng
<BrowserRouter>
  <Routes>
    <Route path="/dashboard" element={<Dashboard />} />
  </Routes>
</BrowserRouter>

3. Kiểm tra path của route lồng nhau

Trong React Router v6, path của route con là tương đối. Đừng thêm tiền tố / hoặc lặp lại đoạn path của cha:

// Sai — path con bắt đầu bằng /
<Route path="/app" element={<AppLayout />}>
  <Route path="/app/dashboard" element={<Dashboard />} />
</Route>

// Đúng — path con là tương đối
<Route path="/app" element={<AppLayout />}>
  <Route path="dashboard" element={<Dashboard />} />
</Route>

Viết path="/app/dashboard" cho route con sẽ khiến React Router xử lý nó như một path tuyệt đối gốc từ root — không phải tương đối với cha. Chỉ cần dùng dashboard và URL đầy đủ sẽ tự động thành /app/dashboard.

4. Xác minh (hoặc tương đương) bao bọc toàn bộ app

Nếu không có router context phía trên <Routes>, mọi thứ sẽ không hoạt động. Kiểm tra lại điểm vào của bạn:

// main.tsx hoặc index.tsx
import { BrowserRouter } from 'react-router-dom';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

Một cái bẫy: nếu bạn đang dùng Remix hoặc TanStack Router, đừng thêm <BrowserRouter> thứ hai vào trên cùng. Các framework này đã cung cấp router context riêng. Hai router context lồng nhau sẽ xung đột nhau và gây ra chính xác lỗi này.

5. Cẩn thận với conditional rendering ẩn các route

Trường hợp này khá tinh vi. Định nghĩa route nằm bên trong một điều kiện mà ở lần render đầu tiên điều kiện đó là false:

// Lỗi: route chỉ render sau khi user được tải
function App() {
  const { user } = useAuth();
  return (
    <Routes>
      {user && <Route path="/dashboard" element={<Dashboard />} />}
    </Routes>
  );
}

Khi trang tải, user vẫn còn là null. Route chưa tồn tại lúc này. Vì vậy truy cập /dashboard ngay lập tức kích hoạt lỗi No routes matched — dù user có thể trở thành truthy sau 50ms. Luôn định nghĩa route một cách vô điều kiện. Kiểm soát quyền truy cập bên trong component hoặc một wrapper:

function RequireAuth({ children }: { children: JSX.Element }) {
  const { user } = useAuth();
  if (!user) return <Navigate to="/login" replace />;
  return children;
}

function App() {
  return (
    <Routes>
      <Route
        path="/dashboard"
        element={
          <RequireAuth>
            <Dashboard />
          </RequireAuth>
        }
      />
      <Route path="/login" element={<Login />} />
    </Routes>
  );
}

Cấu hình hoạt động đầy đủ

Dưới đây là một app React Router v6 tối giản và chính xác — hãy dùng nó làm tài liệu tham khảo khi có sự cố xảy ra:

// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

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

// App.tsx
import { Routes, Route, Navigate } from 'react-router-dom';
import Dashboard from './pages/Dashboard';
import Login from './pages/Login';
import Home from './pages/Home';

export default function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/dashboard" element={<Dashboard />} />
      <Route path="/login" element={<Login />} />
      {/* Catch-all — hiển thị 404 thay vì màn hình trắng */}
      <Route path="*" element={<div>404 Not Found</div>} />
    </Routes>
  );
}

Route catch-all path="*" ở cuối rất đáng thêm vào mọi dự án. Màn hình trắng không cho bạn thông tin gì để debug. Một trang 404 ít nhất cho bạn biết router đang hoạt động và đường dẫn đơn giản là không khớp.

Xác minh đã sửa xong

  • Điều hướng trực tiếp đến URL trên trình duyệt (hard refresh). Component đúng phải được render.
  • Nhấp vào <Link to="/dashboard"> — việc chuyển trang phải xảy ra mà không reload toàn bộ trang.
  • Mở React DevTools, tìm router context, và xác nhận route được khớp hiển thị /dashboard.
  • Kiểm tra console trình duyệt — cảnh báo No routes matched phải biến mất.

Thêm một điều: hash router và browser router

Các triển khai tĩnh (không có server-side routing) có một vấn đề riêng. Gõ trực tiếp /dashboard vào thanh địa chỉ và trình duyệt sẽ gửi request đó đến server của bạn. Server chỉ biết về index.html, vì vậy nó trả về 404 trước khi React được tải.

Hai cách xử lý:

  • Cấu hình server redirect tất cả các path về index.html — cách sửa đúng cho Nginx, Apache, hoặc Cloudflare Pages.
  • Chuyển sang <HashRouter> — URL sẽ thành /#/dashboard, luôn giữ nguyên trên client.
// Cấu hình Nginx cho SPA
location / {
  try_files $uri $uri/ /index.html;
}

Triệu chứng trông giống hệt nhau nhưng nguyên nhân lại khác nhau. Mở tab Network. Response 200 cho file HTML kèm theo No routes matched trong console nghĩa là vấn đề cấu hình routing. Response 404 thẳng từ server nghĩa là vấn đề cấu hình triển khai. Chỉ một bước kiểm tra đó là phân biệt được hai trường hợp ngay lập tức.

Related Error Notes