Navigation و Links

در درس‌های قبل دیدیم چگونه Routeها را تعریف کنیم و پارامترهای مسیر و Query را بخوانیم. اما کاربر چگونه بین این مسیرها حرکت می‌کند؟ در این درس، دو روش اصلی ناوبری در React Router را می‌بینیم: لینک‌های اعلانی و ناوبری برنامه‌نویسی‌شده.

چرا نمی‌توان از تگ a معمولی استفاده کرد

یک تگ <a href="/products"> معمولی، رفتار پیش‌فرض مرورگر را دارد: کلیک روی آن باعث بارگذاری کامل صفحه از سرور می‌شود. همان‌طور که در درس اول این فصل دیدیم، این دقیقاً همان چیزی است که Client-Side Routing می‌خواهد از آن جلوگیری کند؛ چون با هر بارگذاری کامل، State برنامه از بین می‌رود.

کامپوننت Link: جایگزین اعلانی تگ a

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

function Navbar() {
  return (
    <nav>
      <Link to="/">خانه</Link>
      <Link to="/products">محصولات</Link>
    </nav>
  );
}

Link در نهایت یک تگ a واقعی در DOM می‌سازد (برای حفظ قابلیت‌های دسترس‌پذیری و رفتارهایی مثل باز کردن در تب جدید)، اما کلیک روی آن را می‌گیرد، رفتار پیش‌فرض مرورگر را متوقف می‌کند، و به‌جای آن، از همان History API که در درس اول دیدیم استفاده می‌کند تا فقط URL را عوض کند، بدون بارگذاری مجدد.

NavLink: دانستن اینکه مسیر فعلی کدام است

برای نشان دادن این‌که کدام لینک، مربوط به صفحه فعلی است (مثلاً برای استایل‌دهی متفاوت)، نسخه دیگری از Link به نام NavLink وجود دارد که اطلاعات اضافه‌ای در اختیار می‌گذارد:

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

function Navbar() {
  return (
    <NavLink
      to="/products"
      className={({ isActive }) => (isActive ? "active-link" : "")}
    >
      محصولات
    </NavLink>
  );
}

تابعی که به className داده می‌شود، یک آبجکت با فیلد isActive دریافت می‌کند که نشان می‌دهد آیا مسیر فعلی با to این لینک تطبیق دارد یا نه.

ناوبری برنامه‌نویسی‌شده: useNavigate

گاهی ناوبری باید نتیجه یک عمل باشد، نه کلیک مستقیم روی یک لینک؛ مثلاً هدایت کاربر به صفحه دیگر پس از ارسال موفق یک فرم. برای این حالت، از Hook به نام useNavigate استفاده می‌شود:

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

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

  async function handleSubmit(e) {
    e.preventDefault();
    await login();
    navigate("/dashboard");
  }

  return <form onSubmit={handleSubmit}>{/* فیلدها */}</form>;
}

در این الگو، تصمیم ناوبری نتیجه یک رویداد (Submit موفق) است؛ همان تفکیک Event Handler در برابر Effect که در فصل ششم دیدیم، اینجا هم برقرار است: ناوبری پس از یک عمل کاربر، باید داخل همان Event Handler انجام شود، نه در یک Effect جداگانه.

جایگزینی تاریخچه به‌جای افزودن به آن

به‌طور پیش‌فرض، هر ناوبری یک ورودی جدید به تاریخچه مرورگر اضافه می‌کند، یعنی دکمه Back کاربر را به صفحه قبلی برمی‌گرداند. گاهی (مثلاً پس از ورود موفق) نمی‌خواهیم کاربر با دکمه Back به صفحه ورود برگردد؛ برای این حالت، گزینه replace استفاده می‌شود:

navigate("/dashboard", { replace: true });

مثال قابل اجرا

در این مثال شبیه‌سازی‌شده، هم ناوبری با کلیک روی لینک و هم ناوبری برنامه‌نویسی‌شده پس از یک عمل دیده می‌شود.

شبیه‌سازی Link و ناوبری برنامه‌نویسی‌شده
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

کامپوننت Link (و نسخه فعال‌شناس آن، NavLink) جایگزین اعلانی تگ a است و از بارگذاری کامل صفحه جلوگیری می‌کند؛ useNavigate برای ناوبری برنامه‌نویسی‌شده، معمولاً پس از یک عمل در Event Handler، استفاده می‌شود. گزینه replace، افزودن به تاریخچه مرورگر را کنار می‌گذارد. در درس بعدی، به Protected Routes، یعنی محدود کردن دسترسی به برخی مسیرها، می‌پردازیم.