Callback Ref: کنترل دقیق‌تر روی لحظه اتصال به DOM

در درس‌های قبلی این فصل، با روش رایج اتصال Ref به یک عنصر، یعنی دادن یک آبجکت ساخته‌شده با useRef به ویژگی ref، آشنا شدیم. اما React یک روش دیگر هم برای این کار ارائه می‌دهد: دادن یک تابع به‌جای یک آبجکت به ویژگی ref. به این روش، Callback Ref گفته می‌شود.

یادآوری روش معمول

function Box() {
  const boxRef = useRef(null);
  return <div ref={boxRef}>محتوا</div>;
}

در این روش، React پس از قرار گرفتن عنصر در DOM، مقدار boxRef.current را برابر همان عنصر تنظیم می‌کند و هنگام حذف عنصر از DOM، آن را دوباره null می‌کند.

روش Callback Ref: یک تابع به‌جای یک آبجکت

به‌جای دادن یک آبجکت Ref، می‌توان مستقیماً یک تابع به ویژگی ref داد. React این تابع را با خود عنصر DOM (هنگام اتصال) و با null (هنگام قطع اتصال) فراخوانی می‌کند:

function Box() {
  return (
    <div
      ref={(node) => {
        if (node) {
          console.log("عنصر متصل شد:", node);
        } else {
          console.log("عنصر جدا شد");
        }
      }}
    >
      محتوا
    </div>
  );
}

در این حالت، دیگر نیازی به useRef نیست؛ خود تابع، در لحظه اتصال یا جدا شدن عنصر، مستقیماً فراخوانی می‌شود.

چه زمانی Callback Ref مفید است

Callback Ref زمانی مفید است که بخواهیم دقیقاً در همان لحظه‌ای که یک عنصر به DOM متصل یا از آن جدا می‌شود، کاری انجام دهیم؛ بدون نیاز به یک useEffect جداگانه که منتظر بماند و بعد Ref را بررسی کند. یک کاربرد رایج، اندازه‌گیری ابعاد یک عنصر، دقیقاً در لحظه‌ای که برای اولین بار ظاهر می‌شود:

function MeasuredBox() {
  const [height, setHeight] = useState(0);

  return (
    <div
      ref={(node) => {
        if (node) {
          setHeight(node.getBoundingClientRect().height);
        }
      }}
    >
      محتوای این کادر
    </div>
  );
}

در این مثال، به‌محض این‌که عنصر div در DOM قرار می‌گیرد، ارتفاع واقعی آن اندازه‌گیری و در State ذخیره می‌شود؛ بدون نیاز به یک Effect جداگانه که منتظر Mount شدن بماند.

Callback Ref با هر رندر، اگر تابع تازه ساخته شود، دوباره فراخوانی می‌شود

نکته‌ای که باید در نظر داشت این است که اگر یک تابع Inline (مانند مثال‌های بالا) مستقیماً داخل JSX تعریف شود، در هر رندر یک تابع کاملاً جدید ساخته می‌شود. React با مقایسه این تابع جدید با تابع قبلی، متوجه تغییر می‌شود و ممکن است Callback Ref را با null (جدا شدن از نسخه قبلی) و سپس با عنصر جدید (اتصال دوباره) فراخوانی کند. اگر این رفتار مطلوب نیست، باید تابع Callback Ref را با useCallback پایدار نگه داشت؛ موضوعی که با جزئیات کامل در فصل سیزدهم بررسی می‌شود.

Callback Ref در برابر روش معمولی

در بیشتر موقعیت‌های روزمره، روش معمولی با useRef کاملاً کافی است؛ چون معمولاً به‌همراه useEffect استفاده می‌شود و همان نتیجه را می‌دهد. Callback Ref بیشتر برای موقعیت‌های خاصی مفید است که نیاز به واکنش دقیق و فوری، درست در لحظه اتصال یا جدا شدن عنصر، وجود دارد.

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

اندازه‌گیری ارتفاع یک عنصر با Callback Ref
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

Callback Ref یعنی دادن یک تابع، به‌جای یک آبجکت Ref، به ویژگی ref؛ این تابع دقیقاً در لحظه اتصال عنصر به DOM (با خود عنصر) و در لحظه جدا شدن آن (با null) فراخوانی می‌شود. این روش برای واکنش فوری به لحظه اتصال یا جدا شدن یک عنصر مفید است. در درس بعدی به موضوع Ref به‌عنوان Prop در React مدرن می‌پردازیم.