Ref در React یک ویژگی است که به شما امکان میدهد به صورت مستقیم به المانهای DOM دسترسی پیدا کنید و آنها را کنترل کنید. با استفاده از Ref، میتوانید از المانهای DOM برای تعیین ارتفاع و عرض برخی المانها، ردیابی فرم، پخش صوت، انیمیشنهای پیچیده و سایر کاربردها استفاده کنید. برای جزئیات بیشتر در این مورد می توانید دوره جامع React را بررسی کنید. همچنین برای دسترسی به آموزش های بیشتر می توانید به بخش آموزش ری اکت مراجعه کنید.
Ref ها به دو صورت مختلف در React استفاده میشوند:
۱. Ref های ایجاد شده به صورت خودکار توسط React به کار میروند تا به عنوان مشخصههای مشخصی برای کامپوننتهای React کار کنند. این نوع Ref ها به صورت پیشفرض به ریشه کامپوننت دسترسی دارند. این نوع Ref ها را Refهای اشارهگر دهنده مینامند.
2. Ref هایی که به صورت دستی توسط شما ایجاد میشوند. این Ref ها به شما امکان میدهند به صورت مستقیم با عناصر DOM برخورد کنید و آنها را کنترل کنید. این نوع Ref ها را Refهای دستی مینامند.
برای ایجاد Ref دستی در React، ابتدا باید از useRef استفاده کنید. سپس Ref ایجاد شده را به عنوان پارامتر به المان مورد نظر پاس دهید. سپس شما میتوانید با استفاده از current
به Ref دستی خود دسترسی داشته باشید.
کد زیر نحوه پیاده سازی Ref دستی را نشان می دهد:
import React, { useRef, useEffect } from "react";
function MyComponent() {
const myRef = useRef(null);
useEffect(() => {
myRef.current.focus();
}, []);
return <input type="text" ref={myRef} />;
}
در این مثال، با استفاده از useRef یک ref دستی با نام myRef
ایجاد شده است. سپس Ref به عنوان یک پارامتر برای المان input
ارسال شده است.
دوره تخصصی آموزش React
شاید با ری اکت آشنا باشید، اما می دونید یه پروژه بزرگ رو چه طور باید مدیریت کنید؟
در چه سناریوهایی می توان از Ref استفاده کرد؟
ref
در سناریوهای گوناگونی کاربرد دارد. در ادامه چند نمونه از موارد استفاده ref
با توضیح کاربرد هرکدام و یک نمونه با کمک Function Component آورده شده است:
دسترسی به داده های فرم در زمان ارسال فرم
در صورتی که میخواهید در زمان ارسال فرم، اطلاعات ورودی در فیلدهای فرم را دریافت کنید، میتوانید از ref
استفاده کنید.
import React, { useRef } from "react";
function MyForm() {
const inputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
console.log(inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
در این مثال، با استفاده از useRef
یک ref
برای فیلد ورودی تعریف شده است و در handleSubmit
با استفاده از inputRef.current.value
مقدار فیلد ورودی دریافت شده و در کنسول چاپ میشود.
دسترسی به عناصر DOM
اگر نیاز دارید به عناصر DOM مثل input
, select
, یا canvas
دسترسی داشته باشید و به آنها دستوراتی دهید، میتوانید از ref
استفاده کنید.
import React, { useRef, useEffect } from "react";
function MyCanvas() {
const canvasRef = useRef(null);
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
}, []);
return <canvas width="200" height="100" ref={canvasRef} />;
}
در این مثال، با استفاده از useRef
یک ref
برای عنصر canvas
تعریف شده است. سپس با استفاده از useEffect
و درون آن، از canvasRef.current
به عنصر canvas
دسترسی گرفته.
دسترسی به رفرنس دیگری
از جمله مثالهایی که میتوان از ref
برای دسترسی به رفرنس دیگری استفاده کرد، تنظیم مجدد اندازه یک کامپوننت است.
import React, { useState, useRef } from "react";
function ResizableBox() {
const [width, setWidth] = useState(200);
const [height, setHeight] = useState(100);
const resizableBoxRef = useRef(null);
const handleResize = (event) => {
setWidth(event.pageX - resizableBoxRef.current.offsetLeft);
setHeight(event.pageY - resizableBoxRef.current.offsetTop);
};
return (
<div
style={{ width: `${width}px`, height: `${height}px` }}
onMouseMove={handleResize}
ref={resizableBoxRef}
>
Resizable Box
</div>
);
در این مثال، با استفاده از useRef
یک ref
برای عنصر div
تعریف شده است و به آن در ref={resizableBoxRef}
اشاره شده است. در ادامه با استفاده از resizableBoxRef.current.offsetLeft
و resizableBoxRef.current.offsetTop
مقادیر left
و top
عنصر div
در متغیرهای width
و height
قرار میگیرند. سپس در style
این مقادیر به عنوان اندازه width
و height
استفاده شدهاند.
با استفاده از ref
در React میتوان به صورت راحتتر به عناصر DOM دسترسی داشت و کدهای مربوط به آنها را به راحتی تغییر داد.
فوکوس کردن روی یک عنصر
در سناریوی دیگری، ref
میتواند برای فوکوس کردن روی یک عنصر DOM استفاده شود. برای مثال، فرض کنید یک فرم ورود به سایت دارید که شامل دو ورودی برای نام کاربری و رمز عبور است. میتوانید با استفاده از useRef
به عنصری که میخواهید روی آن فوکوس شود، دسترسی داشته باشید.
import React, { useRef } from "react";
function LoginForm() {
const usernameRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
console.log(usernameRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<label>
Username:
<input type="text" ref={usernameRef} />
</label>
<br />
<label>
Password:
<input type="password" />
</label>
<br />
<button type="submit">Login</button>
</form>
);
}
در این مثال، یک ref
با نام usernameRef
برای input
نام کاربری تعریف شده است و به آن با ref={usernameRef}
اشاره شده است. در ادامه با استفاده از usernameRef.current.value
مقدار ورودی نام کاربری در هنگام ثبت فرم در کنسول چاپ میشود.
با استفاده از ref
میتوان به راحتی به عناصر DOM دسترسی داشت و از آنها در کامپوننتهای React استفاده کرد.
مراقب Anti Pattern های Ref باشید
استفاده نادرست از ref
ها در React میتواند باعث به وجود آمدن Anti-pattern هایی شود که برای افزایش عملکرد و بهینهسازی کامپوننتهای React توصیه نمیشوند. در ادامه، چند مثال از این Anti-pattern ها با توضیح کوتاه بیان میشوند:
- استفاده از
ref
در کامپوننتهای بزرگ
استفاده از ref
در کامپوننتهای بزرگ و پیچیده میتواند باعث افزایش پیچیدگی کد شود و برای مدیریت و نگهداری کامپوننتها مشکلاتی را به وجود آورد. بهتر است برای کامپوننتهای پیچیده، از رویکرد دیگری مانند استفاده از Redux یا Context API استفاده کرد.
- استفاده از
ref
به جای props
در برخی موارد، توصیه میشود از ref
به جای props استفاده کرد. به عنوان مثال، اگر میخواهید یک تابع را به یک کامپوننت فرزند پاس بدهید، به جای این کار، میتوانید از props استفاده کنید. استفاده از ref
در این موارد باعث کاهش خوانایی و قابلیت تعمیم کد میشود.
- تغییر وضعیت یک کامپوننت با استفاده از
ref
تغییر وضعیت یک کامپوننت در React باید با استفاده از استیت انجام شود و استفاده از ref
برای تغییر وضعیت یک کامپوننت توصیه نمیشود. به عنوان مثال، اگر بخواهید وضعیت یک کامپوننت با نام Child
را تغییر دهید، به جای استفاده از ref
باید از props استفاده کنید و وضعیت را در کامپوننت والد تغییر دهید.
- تغییر state
از آنجا که مقدار ref به روز رسانی نمی شود، برخی از توسعه دهندگان از آنها برای تغییر در state استفاده می کنند. این عملکرد، یکی از Anti-pattern های بدیهی است که باید به ازای هر مورد با دقت استفاده شود. برای مقداردهی state باید از setState استفاده کرد، به جای آن که از ref استفاده کنید.
به عنوان مثال، فرض کنید یک ماژول دارید که یک شمارنده را نگه می دارد و توسط دو دکمه "افزایش" و "کاهش"، می توانید مقدار شمارنده را تغییر دهید. شما می توانید از یک ref برای نگهداری مقدار شمارنده استفاده کنید، اما تغییر مقدار شمارنده باید با استفاده از setState انجام شود:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const countRef = useRef(count);
const handleIncrease = () => {
setCount(count + 1);
countRef.current = count + 1;
};
const handleDecrease = () => {
setCount(count - 1);
countRef.current = count - 1;
};
const handlePrint = () => {
console.log(`Count: ${count}, CountRef: ${countRef.current}`);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleIncrease}>Increase</button>
<button onClick={handleDecrease}>Decrease</button>
<button onClick={handlePrint}>Print</button>
</div>
);
}
در مثال بالا، برای نگهداری مقدار شمارنده از هر دو useState و useRef استفاده شده است. استفاده از setState در handleIncrease و handleDecrease باعث می شود مقدار شمارنده در state به روز شود، در حالی که استفاده از countRef برای نگهداری مقدار شمارنده به دلیل دسترسی به آخرین مقدار شمارنده، بدون نیاز به render مجدد، امکان پرینت کردن آخرین مقدار شمارنده را فراهم می کند.
استفاده از forwardRef
forwardRef
یک تابع است که به عنوان یک wrapper برای کامپوننت هایی که یک ref
دریافت می کنند، استفاده می شود. این تابع به کامپوننت اجازه می دهد که ref
را برای کامپوننت فرزند خود منتقل کند.
به عنوان یک مثال، فرض کنید می خواهید یک کامپوننت شامل یک input
و یک label
را ایجاد کنید و می خواهید بتوانید با استفاده از ref
این کامپوننت، مقدار input
را به طور مستقیم دسترسی داشته باشید. به جای استفاده از forwardRef
، ممکن است بخواهید کد زیر را بنویسید:
import React, { useRef } from 'react';
function InputWithRef(props, ref) {
const inputRef = useRef(null);
function focus() {
inputRef.current.focus();
}
return (
<div>
<label>{props.label}</label>
<input type="text" ref={inputRef} />
<button onClick={focus}>Focus input</button>
</div>
);
}
const ForwardedInput = React.forwardRef(InputWithRef);
در این مثال، کامپوننت InputWithRef
دارای یک ref
به نام inputRef
است که برای دسترسی به مقدار input
استفاده می شود. همچنین، یک تابع به نام focus
نیز وجود دارد که با فشردن دکمه "Focus input"، مقدار input
را فعال می کند.
سپس با استفاده از React.forwardRef
، کامپوننت InputWithRef
به ForwardedInput
تبدیل می شود. به این ترتیب، می توانیم ref
را برای کامپوننت ForwardedInput
استفاده کنیم:
import React, { useRef } from 'react';
function App() {
const inputRef = useRef(null);
function focusInput() {
inputRef.current.focus();
}
return (
<div>
<ForwardedInput label="Name:" ref={inputRef} />
<button onClick={focusInput}>Focus input</button>
</div>
);
}
export default App;
در این مثال، کامپوننت ForwardedInput
اجازه می دهد که ref
به آن منتقل شود.
خلاصه
Ref در React یک ابزار قدرتمند است که به برنامهنویسان امکان میدهد تا به راحتی به عناصر رابط کاربری دسترسی پیدا کنند و از آنها استفاده کنند. با استفاده از Ref میتوان به سادگی دادههای فرم دریافتی از کاربر را چک کرد، عملیات DOM را انجام داد و به هر یک از عناصر رابط کاربری با استفاده از کد JavaScript دسترسی پیدا کرد.
همچنین، برای جلوگیری از استفاده از الگوهای غلط مانند نگه داشتن اشاره گر به DOM، میتوان از useRef استفاده کرد. این تابع به کامپوننت ها اجازه میدهد که به صورت شیءمانند به یک متغیر اشاره کنند، بدون اینکه نیاز باشد آن را هر بار درخواست کنند.
علاوه بر این، استفاده از useRef به برنامهنویسان اجازه میدهد تا به یک عنصر DOM اشاره کنند و بتوانند آن را به راحتی تغییر دهند بدون اینکه بخواهند به واسطه تغییر وضعیت کامپوننت یا رندر کامپوننت را دوباره رندر کنند.
در نهایت، استفاده از Ref در React میتواند به برنامهنویسان کمک کند تا کدهای قابل خواندن تر، قابل نگهداری تر و ساده تری ایجاد کنند.
چنانچه به دنبال آموزش React هستید، در دوره آموزش ری اکت شرکت کنید
دوره تخصصی آموزش React
دوره جامع آموزش ری اکت رو از دست ندید