مقدمه

یکی از اصول اصلی React این است که شما نباید مستقیماً DOM را دستکاری کنید. شما به صورت «اعلانی» (declarative) به React می‌گویید که UI باید چگونه باشد و خود React مسئولیت به‌روزرسانی DOM را بر عهده می‌گیرد. اما گاهی اوقات، ما نیاز داریم که از این مدل اعلانی فرار کرده و به صورت «دستوری» (imperative) به یک عنصر DOM خاص دسترسی پیدا کنیم.

برای مثال، ممکن است بخواهیم فوکوس را روی یک فیلد ورودی قرار دهیم، یک ویدئو را پخش کنیم، یا موقعیت اسکرول یک عنصر را مدیریت کنیم. برای این موارد نادر اما ضروری، React یک «دریچه فرار» به نام «رفرنس‌ها» یا Refs و هوک useRef را فراهم می‌کند.

useRef چیست؟

هوک useRef یک تابع است که یک شیء قابل تغییر (mutable) را برمی‌گرداند. این شیء یک پراپرتی به نام .current دارد که شما می‌توانید هر مقداری را در آن ذخیره کنید. این شیء در طول تمام رندرهای کامپوننت، پایدار باقی می‌ماند.

useRef دو کاربرد اصلی دارد:

  1. دسترسی به عناصر DOM: شما می‌توانید یک ref را به یک عنصر JSX متصل کنید تا یک ارجاع مستقیم به گره DOM آن در اختیار داشته باشید.
  2. نگهداری مقادیر قابل تغییر بدون رندر مجدد: شما می‌توانید از آن برای ذخیره مقادیری استفاده کنید که با تغییر آنها، نیازی به رندر مجدد کامپوننت نیست (برخلاف useState).

مثال عملی: فوکوس خودکار روی یک ورودی

بیایید یک مثال کلاسیک را بررسی کنیم: یک کامپوننت که به محض رندر شدن، فوکوس را به صورت خودکار روی یک فیلد ورودی قرار می‌دهد.

Copy Icon JAVASCRIPT (React)
import { useRef, useEffect } from 'react';

function FocusInput() {
  // 1. Create a ref object
  const inputRef = useRef(null);

  useEffect(() => {
    // 3. The DOM element is now available in inputRef.current
    // We can call browser DOM APIs on it, like focus().
    inputRef.current.focus();
  }, []); // Run this effect only once on mount

  return (
    <div>
      <p>The input field below should be focused on page load.</p>
      <!-- 2. Attach the ref to the input element -->
      <input ref={inputRef} type="text" />
    </div>
  );
}

مراحل کار با Ref

این کد از سه مرحله اصلی تشکیل شده است:

  1. ایجاد Ref: ما با فراخوانی useRef(null) یک شیء ref ایجاد می‌کنیم. مقدار اولیه null به این معنی است که در ابتدا به هیچ چیزی اشاره نمی‌کند.
  2. اتصال Ref: ما این شیء ref را به اتریبیوت خاص ref در عنصر <input> خود پاس می‌دهیم. این کار به React می‌گوید که "لطفاً یک ارجاع به گره DOM واقعی این <input> را در پراپرتی .current شیء inputRef قرار بده."
  3. استفاده از Ref: پس از اینکه React کامپوننت را رندر کرده و DOM را ایجاد کرد، inputRef.current به گره <input> واقعی اشاره خواهد کرد. ما در داخل یک useEffect (با آرایه وابستگی خالی تا فقط یک بار اجرا شود)، متد بومی DOM یعنی .focus() را روی inputRef.current فراخوانی می‌کنیم.

useRef در مقابل useState

درک تفاوت بین این دو هوک بسیار مهم است.

  • useState: تغییر مقدار آن با تابع setter یک رندر مجدد را کلید می‌زند. از آن برای نگهداری داده‌هایی استفاده کنید که مستقیماً در UI نمایش داده می‌شوند.
  • useRef: تغییر پراپرتی .current آن، باعث رندر مجدد نمی‌شود. از آن برای نگهداری مقادیری استفاده کنید که برای منطق داخلی کامپوننت نیاز دارید اما بر روی UI تأثیر مستقیم ندارند (مانند ID یک تایمر setInterval) یا برای دسترسی مستقیم به DOM.

در این درس، با هوک useRef به عنوان یک «دریچه فرار» برای دسترسی مستقیم به DOM و نگهداری مقادیر قابل تغییر بدون ایجاد رندر مجدد آشنا شدیم. این هوک ابزار قدرتمندی برای مدیریت فوکوس، انیمیشن‌ها و یکپارچه‌سازی با کتابخانه‌های DOM-محور است. در درس بعدی، به سراغ هوک useMemo خواهیم رفت و یاد می‌گیریم که چگونه با به خاطر سپردن نتایج محاسبات سنگین، از کارهای تکراری جلوگیری کرده و عملکرد اپلیکیشن خود را بهینه کنیم.