ESC را فشار دهید تا بسته شود

تفاوت useRef و useState در React

وقتی که ما قصد داریم داده ای رو توی برنامه ری اکتی خودمون ذخیره کنیم باید بررسی کنیم که توی “چرخه حیات” کامپونتت (component lifecycle)، نیاز داریم که داده تغییر کنه یا نه!

منم از “چرخه حیات” خوشم نمیاد اما مجبورم برای فارسی نوشتن ازش استفاده کنم. پس هرجا میگم چرخه حیات منظورم lifecycle هستش. اگر lifecycle توی ری اکت هم نمیدونین چیه اینجا کلیک کنین

اگر داده قرار نیست تغییر کنه می‌تونیم اون رو به روش معمول و توی const ذخیره کنیم.

اما اگر قراره این داده‌ی ذخیره شده در طول چرخه حیات کامپوننت تغییر کنه، نیازه که از یکی از هوک‌های useRef و یا useState استفاده کنیم.

بررسی هوک useState

از این هوک برای مدیریت داده های یک کامپوننت استفاده می‌کنیم که در هر زمانی ممکنه تغییر کنن و روی re-render شدن کامپوننت هم تاثیر داره.

این هوک معمولا درون خودش یک مقدار اولیه می‌گیره که می‌تونه از هر نوع داده ای (آبجکت، آرایه، اعداد، رشته و….) باشه و به ما یه آرایه برمی‌گردونه که شامل دو مقدار هست یکی متغیری که داده اولیه رو توی خودش ذخیره می‌کنه و یکی دیگه که معمولا با set شروع میشه تابعی هست که می‌تونیم مقدار اولیه رو تغییر بدیم.

بریم کدش رو ببینیم:

// import hook from react
import { useState } from "react";

export function App() {
  //declared useState hook
  // initail value = 0 (put in count)
  // count = 0
  // setCount => function for change value of count
  const [count, setCount] = useState(0); 
  
  return (
      <div>
        // setCount increase value of count with every click     
        <button onClick={() => setCount((count) => count + 1)}>Increase Count</button>
        // show count here
        <p>value of count is : {count}</p>  
      </div>
  );
}

توضیح کد بالا

  • اول useState رو به کامپونتت اضافه کردیم
  • useState به ما آرایه برمیگردونه که شامل دو مقدار شده count و setCount
  • useState توی خودش یک مقدار اولیه میگیره که ما اون رو برابر “۰” قرار دادیم
  • مقدار اولیه ما که “۰” هست توی count قرار میگیره که هر جای کامپونتت قابل مشاهده اس (خط ۱۶)
  • و یک تابع دیگه که با set شروع میشه به اسم setCount که ما اون رو روی یک دکمه قرار دادیم که با هر بار کلیک یدونه مقدار count رو افزایش میده (که با هربار کلیک کردن و آپدیت مقدار count کامپونتت ما re-render میشه)

بررسی هوک useRef

هوک useRef برای ساختن یک ref توی کامپونتت استفاده میشه که این ref یک آبجکته که توی این آبجکت property مهمی به اسم current داره که همیشه value رو توی خودش نگه میداره (مثل کاری که count توی useState میکرد).

اساسا ref رو به یک DOM و یا یک instance از یک کامپونتت ارجاع می‌دیم که می‌تونیم مقدار value رو بخونیم و یا آپدیت کنیم با استفاده از property که گفتیم current هستش

بریم کدش رو ببینیم

// import useRef
import { useRef } from "react";

export function App() {
  // declared useRef with iniialValue '0'
  let ref = useRef(0) 
  // function to increase value
  function handleIncreaseCount(){
    //update value with 'current' property
    ref.current++
     console.log(`clicked ${ref.current} times`);
  }
  return (
      <div> 
        <button onClick={handleIncreaseCount}>Increase Count</button> 
      </div>
  );
}

توضیح کد بالا

  • اول useRef رو به کامپونتت اضافه کردیم
  • بعد ref رو تعریف کردیم با مقدار اولیه “۰” که این ref یه آبجکت به ما برمیگردونه که مقدار value ما که “۰” هستش توی property به اسم current ذخیره شده
  • یه تابع به اسم handleIncreaseCount تعریف کردیم که مقدار value مارو هر بار آپدیت میکنه و یدونه افزایش میده که با current به اون مقدار دسترسی داریم
  • در آخر هم یه دکمه داریم که با هر بار کلیک تابع مارو فراخوانی میکنه و value رو افزایش میده.

امیدوارم تونسته باشم این دوتا هوک مهم رو خوب توضیح داده باشم 💙🫡

تفاوت State و Ref

رندر شدن

توی ری اکت state ها همیشه براساس مکانیزمی که دارن باعث rerender شدن کامپونتت بعد از هربار تغییرشون میشن (یعنی هربار مقدار state عوض بشه کامپونتت هم rerender میشه. و همینطور اگر توی کامپوننت props داشته باشیم هم علاوه بر state با تغییر props هم باز rerender شدن رو داریم.

با هربار تغییر state و یا props ری اکت میاد مقدار قبلی state رو با مقدار جدیدی که دریافت کرده مقایسه میکنه و اون قسمت رو آپدیت میکنه و ری رندر اتفاق میوفته اما ref هربار مقدارش یا همون value تغییر کنه rerender مجدد توی کامپونتت اتفاق نمیوفته اصطلاحا میگن ref مستقیما به چرخه حیات مرتبط نیست.

نتیجه اینکه اگر تو میخوای ui صفحه با هربار آپدیت داده ها تغییراتی بکنه بهتره که از useState و state ها استفاده کنی اما اگر میخوای این آپدیت شدن داده ها تاثیری روی ui نذاره بهتره از useRef و ref استفاده کنی که با هربار تغییرش کامپوننت rerender نشه.

تغییر پذیر بودن

توی کار با state شما فقط نمیتونی مستقیما مقدارش رو تغییر بدی و فقط میشه مقدار اون رو با استفاده از تابعش که با set شروع میشه تغییر بدی (مثال setCount که میومد و count رو تغییر میداد) این کار باعث میشه جریان داده مشخصه باشه و موقع دیباگ کردن هم بدونی مشکل از کجاست.

اما در ref برعکسه و میتونی اون رو مستقیما با هر تابعی که خودت تعریف میکنی تغییرش بدی چون گفتیم ref خارج از چرخه حیات کار میکنه و تغییراتش تاثیری روی ری رندر شدن نداره (چونکه ref تابع بروزسانی برای خودش نداره در صورتیکه state ها خودشون تابع دارن همون setCount مثلا)

عملیات‌های Read/Write

تابع setter توی useState (منظور از setter همون تابعی بود که مقدار state رو آپدیت میکرد و با set شروع میشد) اجازه میده تو مقدار داده رو آپدیت کنی

  • یک عملیات read داریم که تو میتونی قبل از تغییر مقدار اولیه توی state رو بخونی و بهش دسترسی داشته باشی
  • همینطور یک عملیات write داریم که تو می‌تونی با استفاده از setter مقدارت رو تغییر بدی به چیزی که انتظار داری و ازش میخوای

عملیات read زمانی اتفاق میوفته که شما توی کامپونتت مستقیما به اون مقدار state دسترسی داشته باشین

مثال زیر رو دوباره چک کنیم

import { useState } from "react";
export function App() {
  const [isAdmin, setIsAdmin] = useState(true); 
  return (
    <button onClick={() => setIsAdmin(!isAdmin)}>Change Status</button>
    <p>Admin status is : {isAdmin}</p>
  );
}

می‌بینیم که ما مستقیما به مقدار {isAdmin} که برابر true هست دسترسی داریم پس توی UI قابل مشاهده اس.

اما از برای کار با ref برای تغییر value که از current قابل دسترسه توی زمانی که داره re-render اتفاق میوفته ممکنه باعث ناسازگاری بشه (چونکه گفتیم ref خارج از چرخه حیات ری اکت کار میکنه) و بین virtual DOM و actual DOM اختلال ایجاد کنه.

نتیجه اینکه بهتره حرف ری اکت رو گوش بدیم و بخاطر اینکه متوجه رفتار کامپونتت توی آپدیت و rerender ها باشیم، بهتره وقتی rerender داره اتفاق میوفته مقدار ref رو تغییر ندیم.

ماندگاری داده ها

چه ref و چه state هر دو مقدار داده ای که دارن رو بین هر رندر و یا ری رندر حفظ میکنن و باعث تغییر نمیشن. پس مقادیرشون همیشه قابل دسترسه و از بین نمیره و میتونین هر زمان بهش دسترسی داشته باشین

بروزرسانی ها

توی state آپدیت شدن و بروزرسانی حالت asynchronous هستش پس ممکنه بلافاصله آپدیت رو نبینید و با اندکی تاخیر از بقیه المان ها بروز بشه (البته بستگی به باقی عملیات ها داره)

اما توی ref آپدیت شدن به صورت synchronous اتفاق میوفته یعنی همه به ترتیب انجام میشن و باید عملیات قبلی کامل بشه تا عملیات جدید شروع بشه.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *