آموزش React: راهنمای کامل Ref ها در React
عباس سپهوند
عباس سپهوند
  • 1402/02/18
  • 15 دقیقه
  • 1 نظر

آموزش React: راهنمای کامل Ref ها در React

در این مقاله از سری مقالات آموزش React می بینیم که Ref ها در React چه کاربردی دارند و چگونه می توان از آن ها به شکل موثری استفاده کرد. همچنین می بینیم که در چه سناریوهایی بهتر است از Ref ها استفاده کنیم و در چه شرایطی نباید از آن ها استفاده کرد

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 ها با توضیح کوتاه بیان می‌شوند:

  1. استفاده از ref در کامپوننت‌های بزرگ

استفاده از ref در کامپوننت‌های بزرگ و پیچیده می‌تواند باعث افزایش پیچیدگی کد شود و برای مدیریت و نگهداری کامپوننت‌ها مشکلاتی را به وجود آورد. بهتر است برای کامپوننت‌های پیچیده، از رویکرد دیگری مانند استفاده از Redux یا Context API استفاده کرد.

  1. استفاده از ref به جای props

در برخی موارد، توصیه می‌شود از ref به جای props استفاده کرد. به عنوان مثال، اگر می‌خواهید یک تابع را به یک کامپوننت فرزند پاس بدهید، به جای این کار، می‌توانید از props استفاده کنید. استفاده از ref در این موارد باعث کاهش خوانایی و قابلیت تعمیم کد می‌شود.

  1. تغییر وضعیت یک کامپوننت با استفاده از ref

تغییر وضعیت یک کامپوننت در React باید با استفاده از استیت انجام شود و استفاده از ref برای تغییر وضعیت یک کامپوننت توصیه نمی‌شود. به عنوان مثال، اگر بخواهید وضعیت یک کامپوننت با نام Child را تغییر دهید، به جای استفاده از ref باید از props استفاده کنید و وضعیت را در کامپوننت والد تغییر دهید.

  1.  تغییر 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

دوره جامع آموزش ری اکت رو از دست ندید

دیدگاه

برای ارسال دیدگاه های خود ابتدا وارد شوید یا ثبت نام کنید

ورود یا ثبت نام
_zakarya_kurd_
1402/07/24 - 13:34

خیلی عالی بود استاد سپهوند ممنون بابت مقاله پر کاربردتون . امیدوارم که همیشه موفق باشید ❤

عباس سپهوند
عباس سپهوند

برنامه نویس و توسعه دهنده نرم افزار

مشاهده پروفایل
5 مقاله اخیر

آموزش React: راهنمای کامل useCallback

عباس سپهوند
زمان مطالعه: 40

آموزش React: راهنمای کامل useEffect

عباس سپهوند
زمان مطالعه: 25

آموزش React: راهنمای کامل Ref ها در React

عباس سپهوند
زمان مطالعه: 15
مشاهده همه مقالات