هوک useRef (useRef)
هوک useRef در ری اکت کمک می کند یک مقدار را بین رندرها نگه داری، بدون این که با هر تغییر، کامپوننت دوباره رندر شود. مثل یک دفترچه کوچک کنار دستت که ری اکت آن را نمی بیند، اما تو همیشه می توانی داخلش بنویسی.
هوک useRef در ری اکت چیست؟
هوک (Hook) یعنی تابع کمکی ری اکت که به ما قابلیت های خاص می دهد. useRef در ری اکت یک شی می سازد که خاصیت current دارد. هر مقداری را داخل current بگذاری، بین رندرها حفظ می شود.
برخلاف state که با useState تعریف می شود، تغییر current باعث رندر دوباره نمی شود. بنابراین برای شمارش رندرها، نگه داشتن مقدار قبلی یا کار با DOM خیلی کاربردی است.
اگر تازه با هوک ها آشنا شده ای، بهتر است اول صفحه هوکس در ری اکت و بعد هوک useState را بخوانی، بعد برگردی سراغ useRef در ری اکت.
استفاده از useRef بدون رندر دوباره
اگر بخواهیم تعداد رندر شدن یک کامپوننت را با useState بشماریم، وارد حلقه بی نهایت می شویم؛ چون خود useState دوباره رندر ایجاد می کند. اما useRef در ری اکت این مشکل را ندارد.
در مثال زیر، هر بار که ورودی تغییر می کند، یک رندر جدید انجام می شود و ما تعداد رندرها را در count.current ذخیره می کنیم.
مثال: شمارش تعداد رندر با useRef در ری اکت
import { useState, useRef, useEffect } from "react";
import { createRoot } from "react-dom/client";
function App() {
const [inputValue, setInputValue] = useState("");
const count = useRef(0);
useEffect(() => {
count.current = count.current + 1;
});
return (
<>
<p>
Type in the input field:
</p>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<h1>
Render Count: {count.current}
</h1>
</>
);
}
createRoot(document.getElementById("root")).render(
<App />
);
تابع useRef(0) یک شی مثل {current: 0} برمی گرداند. ما فقط مقدار count.current را عوض می کنیم، اما خود کامپوننت به خاطر این تغییر دوباره رندر نمی شود.
نکته: برای داده هایی که فقط برای لاگ، شمارش داخلی یا کارهای کمکی هستند، useRef در ری اکت انتخاب بهتری از state است.
دسترسی مستقیم به DOM با useRef
گاهی لازم داریم مستقیماً به یک عنصر DOM دسترسی بگیریم؛ مثلاً روی input فوکوس کنیم. DOM (Document Object Model) همان نمای درختی صفحه در مرورگر است.
در useRef در ری اکت، می توانیم یک ref بسازیم، آن را به input وصل کنیم و بعد با current به خود عنصر برسیم.
- یک ref می سازیم: const inputElement = useRef();
- آن را در JSX روی ref قرار می دهیم.
- بعداً با inputElement.current به عنصر دسترسی می گیریم.
مثال: فوکوس کردن روی input با useRef در ری اکت
import { useRef } from "react";
import { createRoot } from "react-dom/client";
function App() {
const inputElement = useRef();
const focusInput = () => {
inputElement.current.focus();
};
return (
<>
<input
type="text"
ref={inputElement}
/>
<button onClick={focusInput}>
Focus Input
</button>
</>
);
}
createRoot(document.getElementById("root")).render(
<App />
);
اینجا وقتی دکمه را می زنی، تابع focusInput اجرا می شود و inputElement.current.focus() کاری می کند که نشانگر تایپ روی input قرار بگیرد؛ بدون نیاز به state.
پیگیری مقدار قبلی state با useRef
گاهی لازم داریم مقدار قبلی state را بدانیم؛ مثلاً ببینیم کاربر چه چیزی قبلاً نوشته است. چون useRef در ری اکت بین رندرها مقدار را نگه می دارد، می توانیم مقدار قبلی را آنجا ذخیره کنیم.
در مثال زیر، inputValue با useState نگه داشته می شود و previousInputValue با useRef مقدار قبلی را حفظ می کند. هر بار که inputValue عوض می شود، داخل useEffect مقدار جدید را در ref ذخیره می کنیم.
مثال: نگه داشتن مقدار قبلی با useRef در ری اکت
import { useRef, useState, useEffect } from "react";
import { createRoot } from "react-dom/client";
function App() {
const [inputValue, setInputValue] = useState("");
const previousInputValue = useRef("");
useEffect(() => {
previousInputValue.current = inputValue;
}, [inputValue]);
return (
<>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<h2>
Current Value: {inputValue}
</h2>
<h2>
Previous Value: {previousInputValue.current}
</h2>
</>
);
}
createRoot(document.getElementById("root")).render(
<App />
);
اینجا ترکیبی از useState، useEffect و useRef در ری اکت داریم. useEffect هر بار که inputValue عوض می شود، previousInputValue.current را به مقدار جدید به روزرسانی می کند.
نکته: اگر useRef برایت جا نیفتاد، برگرد صفحه هوک useEffect را دقیق تر بخوان، چون این دو معمولاً کنار هم استفاده می شوند.
برای مرور دوباره مفهوم useRef در ری اکت همیشه می توانی به همین صفحه برگردی یا از لینک useRef در ری اکت در منوی UnderDevelops استفاده کنی.
جمع بندی سریع
- useRef در ری اکت مقدار را بین رندرها نگه می دارد.
- تغییر current باعث رندر دوباره نمی شود.
- با useRef می توانی مستقیماً به عناصر DOM برسـی.
- برای نگه داشتن مقدار قبلی state، useRef گزینه خوبی است.
- برای منطق رابط کاربری، هنوز useState و useEffect اصلی ترین ابزارها هستند.