مدیریت رویدادها در React

در چند درس گذشته، بارها از onClick و onChange استفاده کردیم بدون اینکه دقیق توضیح دهیم رویدادها در React چگونه کار می‌کنند. در این درس به‌طور مشخص به نحوه مدیریت رویدادها می‌پردازیم؛ موضوعی که پایه اصلی تعامل کاربر با هر فرم و رابط کاربری است.

تفاوت نحوی با HTML معمولی

در HTML معمولی، رویدادها معمولاً با نام کوچک و به‌صورت رشته نوشته می‌شوند، مثلاً onclick="handleClick()". در JSX، نام رویدادها به شیوه camelCase نوشته می‌شوند و مقدار آن‌ها، به‌جای رشته، یک تابع جاوااسکریپت است:

// HTML معمولی
// <button onclick="handleClick()">کلیک</button>

// JSX
function App() {
  function handleClick() {
    console.log("دکمه کلیک شد");
  }

  return <button onClick={handleClick}>کلیک</button>;
}

یک اشتباه رایج: فراخوانی تابع به‌جای ارسال آن

یکی از اشتباهات رایج، نوشتن onClick={handleClick()} به‌جای onClick={handleClick} است. تفاوت این دو بسیار مهم است:

// اشتباه: تابع بلافاصله در زمان رندر اجرا می‌شود
<button onClick={handleClick()}>کلیک</button>

// درست: خود تابع، بدون اجرا، به onClick داده می‌شود
<button onClick={handleClick}>کلیک</button>

در حالت اول، چون از پرانتز استفاده شده، تابع بلافاصله هنگام رندر شدن کامپوننت اجرا می‌شود، نه هنگام کلیک کاربر. React انتظار دارد مقدار onClick یک ارجاع به تابع باشد، نه نتیجه اجرای آن.

ارسال آرگومان به Event Handler

اگر نیاز باشد هنگام فراخوانی یک Handler، آرگومانی هم به آن بدهیم، از یک Arrow Function میانی استفاده می‌کنیم تا از اجرای زودهنگام تابع جلوگیری شود:

function ProductList({ items }) {
  function handleRemove(id) {
    console.log("حذف آیتم", id);
  }

  return (
    <ul>
      {items.map((item) => (
        <li key={item.id}>
          {item.name}
          <button onClick={() => handleRemove(item.id)}>حذف</button>
        </li>
      ))}
    </ul>
  );
}

در اینجا () => handleRemove(item.id) یک تابع جدید است که فقط هنگام کلیک اجرا می‌شود و در آن لحظه، handleRemove را با مقدار صحیح item.id فراخوانی می‌کند.

آبجکت رویداد (SyntheticEvent)

وقتی یک تابع Handler فراخوانی می‌شود، React یک آبجکت رویداد به آن پاس می‌دهد که معمولاً e یا event نامیده می‌شود. این آبجکت اطلاعاتی مانند عنصری که رویداد روی آن رخ داده (e.target) را در خود دارد و رفتاری بسیار شبیه به رویداد استاندارد مرورگر دارد، اما توسط خود React مدیریت و در سراسر مرورگرهای مختلف یکسان‌سازی می‌شود.

function Form() {
  function handleSubmit(e) {
    e.preventDefault(); // جلوگیری از رفتار پیش‌فرض ارسال فرم
    console.log("فرم ارسال شد");
  }

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">ارسال</button>
    </form>
  );
}

متد e.preventDefault() یکی از پرکاربردترین متدهای این آبجکت است؛ برای مثال، از رفرش شدن کامل صفحه هنگام ارسال یک فرم جلوگیری می‌کند تا بتوانیم منطق ارسال را خودمان با جاوااسکریپت مدیریت کنیم.

رویدادهای رایج دیگر

علاوه بر onClick و onChange که تا اینجا زیاد دیده‌ایم، رویدادهای دیگری هم در برنامه‌های واقعی رایج هستند؛ مانند onSubmit برای فرم‌ها، onFocus و onBlur برای ورود و خروج فوکوس از یک عنصر، و onKeyDown برای واکنش به فشردن کلیدهای صفحه‌کلید.

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

مدیریت رویداد کلیک با ارسال آرگومان
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

رویدادها در JSX با نام camelCase نوشته می‌شوند و مقدار آن‌ها همیشه باید ارجاع به یک تابع باشد، نه نتیجه اجرای آن. برای ارسال آرگومان به یک Handler، از یک Arrow Function میانی استفاده می‌کنیم. آبجکت رویداد، اطلاعات و متدهای مفیدی مانند preventDefault را در اختیار می‌گذارد. در درس بعدی، دوباره به عناصر فرم و نحوه تبدیل آن‌ها به Controlled Components می‌پردازیم.