ReactNext
React-documentationIntermediate-2

4.1 Referencing values

Welcome to React Next Documentation Bangla

এই পার্টে আমরা সর্বপ্রথম useRef হুক নিয়ে কথা বলবো।

রিয়াক্টে আমরা সাধারণত ডেটা সংরক্ষণ ও পরিচালনার জন্য স্টেট (state) ব্যবহার করি। স্টেট আমাদের প্রতিবার কোনো তথ্য পরিবর্তিত হলে সেই অনুযায়ী ইউজার ইন্টারফেস (UI) আপডেট করতে সাহায্য করে। কিন্তু এমন কিছু পরিস্থিতি আসে যখন আমরা কোনো মান (value) সংরক্ষণ করতে চাই, যা আপডেট হলেও ইউজার ইন্টারফেস রি-রেন্ডার না হয়। আর ঠিক এই কাজটি করতে আমাদের সাহায্য করে useRef হুক।

কেন useRef দরকার?

স্টেট ব্যবহার করলে রিয়াক্ট সেই কম্পোনেন্টটিকে প্রতিবার রি-রেন্ডার করে। কিন্তু কখনো কখনো আমরা এমন কিছু তথ্য রাখতে চাই, যা শুধু আমাদের জন্য মেমোরিতে সংরক্ষণ থাকবে, কিন্তু তা পরিবর্তন হলেও UI বা কম্পোনেন্ট রি-রেন্ডার হবে না। যেমন ধরো, তোমার একটা ক্লিক কাউন্টার দরকার যেখানে বাটনে ক্লিক করলে শুধু সংখ্যা বাড়বে, কিন্তু বারবার পুরো কম্পোনেন্ট রি-রেন্ডার হবে না। এখানে আমরা useRef ব্যবহার করে সহজেই কাজটি করতে পারি।

useRef একটি হুক যা তোমাকে সরাসরি DOM-এ কোনো মান ধরে রাখতে সাহায্য করে। এটি স্টেটের মতোই কিছুটা কাজ করে, তবে এর পার্থক্য হলো—যখনই আমরা useRef এর ভ্যালু পরিবর্তন করি, তখন কম্পোনেন্ট রি-রেন্ডার হয় না।

কিভাবে useRef ব্যবহার করতে হয়?

useRef ব্যবহার করা বেশ সহজ। চলো, আমরা ধাপে ধাপে দেখি কিভাবে এটি ব্যবহার করতে হয়।

প্রথমে useRef কে রিয়াক্ট থেকে ইম্পোর্ট করে নিতে হবে

import { useRef } from "react";

useRef আমাদের কম্পোনেন্টে ব্যবহার করার জন্য রিয়াক্ট থেকে সরাসরি ইম্পোর্ট করতে হয়।

এরপর useRef কল করতে হবে এবং একটি ইনিশিয়াল ভ্যালু দিতে হবে

const ref = useRef(0);

এখানে ref নামে একটি রেফারেন্স তৈরি হলো, এবং আমরা এতে 0 ইনিশিয়াল ভ্যালু দিয়েছি। এখন এই ref আসলে একটি অবজেক্ট (object), যার মধ্যে current নামের একটি প্রপার্টি আছে। এই current প্রপার্টির মধ্যেই আমাদের ইনিশিয়াল ভ্যালুটি সংরক্ষিত থাকবে। যেমন, যদি আমরা console.log(ref) করি, তাহলে দেখতে পাবো এমন কিছু:

{
  current: 0;
}

useRef এর ভ্যালু পড়া বা পরিবর্তন করা যায়

useRef ব্যবহার করে আমরা যেকোনো মান পড়তে বা পরিবর্তন করতে পারি। যেমন, ধরো আমাদের ref এর মান 0 থেকে বাড়িয়ে 1 করতে চাই। আমরা সেক্ষেত্রে সহজেই ref.current এ নতুন ভ্যালু দিতে পারি। চলো, আমরা একটি উদাহরণ দেখি যেখানে এটি ব্যবহার করা হয়েছে।

উদাহরণ: বাটনে ক্লিক গুনে রাখা

আমরা একটি ছোট প্রোগ্রাম বানাবো যেখানে বাটনে ক্লিক করলে এলার্টে দেখাবে মোট কতবার ক্লিক করা হয়েছে।

import { useRef } from "react";
 
export default function App() {
  const ref = useRef(0);
 
  function handleCountClick() {
    ref.current = ref.current + 1;
    alert(`You clicked the button ${ref.current} times`);
  }
 
  return <button onClick={handleCountClick}>Click me to count</button>;
}

এখানে আমরা কীভাবে useRef ব্যবহার করেছি, সেটি একটু খেয়াল করো:

  1. ইনিশিয়াল ভ্যালু: আমরা useRef এর মাধ্যমে ref এর ইনিশিয়াল ভ্যালু 0 দিয়েছি।
  2. ভ্যালু আপডেট: handleCountClick ফাংশনে আমরা ref.current এর মান 1 করে বাড়িয়েছি প্রতিবার।
  3. রি-রেন্ডার এড়ানো: ref.current পরিবর্তন হলেও কম্পোনেন্ট রি-রেন্ডার হয়নি। এটা useRef এর একটি বিশেষত্ব।
  4. UI-তে সরাসরি না দেখানো: আমরা ref.current এর মান এলার্টে দেখিয়েছি, কিন্তু সরাসরি UI-তে দেখাইনি। যদি সরাসরি UI-তে দেখাতে চাইতাম, তবে আমাদের স্টেট ব্যবহার করতে হতো।

useRef ব্যবহারে কিছু গুরুত্বপূর্ণ বিষয়

  • রি-রেন্ডার এড়াতে: useRef এর ভ্যালু পরিবর্তন করলে কম্পোনেন্ট রি-রেন্ডার হয় না। তাই এটি এমন ডেটা ধরে রাখার জন্য ভালো, যা আমাদের শুধু ব্যাকগ্রাউন্ডে দরকার, কিন্তু UI তে দেখানোর প্রয়োজন নেই।
  • স্টেটের বিকল্প নয়: useRef স্টেটের বিকল্প নয়। যদি তোমার এমন কোনো তথ্য দরকার যা UI-তে দেখাবে বা পরিবর্তিত হলে UI আপডেট হবে, তাহলে state ব্যবহার করাই ঠিক।
  • DOM রেফারেন্স: useRef শুধু ভ্যালু নয়, সরাসরি DOM রেফারেন্স ধরে রাখার জন্যও ব্যবহার করা যায়। ধরো, একটি input ফিল্ডে সরাসরি ফোকাস করতে চাচ্ছো, সেক্ষেত্রে useRef ব্যবহার করা যাবে।

এইভাবেই useRef কাজ করে। এটি একটু বুঝে, যেখানে দরকার সেখানে ব্যবহার করলে অনেক সুবিধা পাওয়া যায়। তবে অতিরিক্ত ব্যবহার করলে রিয়াক্টের নিয়ন্ত্রণের বাইরে চলে যেতে পারে, তাই সাবধানে ব্যবহার করা উচিত।

Storing a Reference or Value in a Ref (ref এর মধ্যে কোন রেফারেন্স বা মান সংরক্ষণ করা)

আমরা useRef হুকের মাধ্যমে current প্রপার্টির মধ্যে একটি রেফারেন্স বা মান সংরক্ষণ করতে পারি, যা কম্পোনেন্টের স্টেট পরিবর্তন হলেও হারিয়ে যায় না। অর্থাৎ, ref হলো এমন এক ধরনের স্টোরেজ যা রিয়াক্ট কম্পোনেন্ট যতবার রি-রেন্ডার হোক না কেন, সেই স্টোর করা ডেটা ধরে রাখতে সক্ষম।

চলুন এটি একটি উদাহরণ দিয়ে বুঝে নেই। এখানে আমরা একটি স্টপওয়াচ তৈরি করবো যা স্টার্ট এবং স্টপ করার সাথে সাথে সময় গুনবে এবং UI-তে সেই সময় দেখাবে।

import { useState } from "react";
 
export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null); // যখন আমরা স্টার্ট বাটনে ক্লিক করি তখনকার সময় স্টেট দিয়ে ম্যানেজ করছি
  const [now, setNow] = useState(null); // স্টার্ট করার পর বর্তমান পর্যন্ত কত সময় গেছে সেটি এই স্টেট দিয়ে ট্র্যাক করি
 
  function handleStart() {
    setStartTime(Date.now());
    setNow(Date.now());
 
    setInterval(() => {
      setNow(Date.now());
    }, 10);
  }
 
  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }
 
  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>Start</button>
    </>
  );
}

Interval Clear করার জন্য useRef ব্যবহার

এখন আমাদের প্রয়োজন স্টপওয়াচকে বন্ধ করার জন্য interval পরিষ্কার করা। কিন্তু এখানে একটি সমস্যা আছে: interval টা handleStart ফাংশনের ভেতরে ডিফাইন করা আছে, তাই সরাসরি clearInterval কল করতে interval এর রেফারেন্স আমরা পাবো না। এখানে useRef আমাদের এই রেফারেন্স স্টোরেজে সাহায্য করবে।

ref.current এর মধ্যে interval এর রেফারেন্স স্টোর করে আমরা যে কোনো সময় এটি clearInterval(ref.current) দিয়ে পরিষ্কার করতে পারি।

কেন useRef ব্যবহার জরুরি, সাধারণ ভ্যারিয়েবল কেন না

আমরা যদি জাভাস্ক্রিপ্টের একটি সাধারণ ভ্যারিয়েবলে interval রেফারেন্স রাখি, তবে প্রতিবার রি-রেন্ডারের সময় ভ্যারিয়েবলটি নতুনভাবে সেট হয়ে যাবে, এবং আমাদের স্টোর করা মান হারিয়ে যাবে। কিন্তু useRef একটি ফাংশন ও রেন্ডারের বাইরে থাকে, তাই কম্পোনেন্ট যতবার রি-রেন্ডার হোক না কেন, ref.current এর মান অপরিবর্তিত থাকে। এ কারণে এটি একটি স্টোরেজ হিসেবে কার্যকর।

পুরো উদাহরণ useRef দিয়ে

import { useState, useRef } from "react";
 
export default function Stopwatch() {
  const ref = useRef(null); // interval রেফারেন্স সংরক্ষণের জন্য
  const [startTime, setStartTime] = useState(null);
  const [now, setNow] = useState(null);
 
  function handleStart() {
    setStartTime(Date.now());
    setNow(Date.now());
 
    ref.current = setInterval(() => {
      setNow(Date.now());
    }, 10);
  }
 
  function handleStop() {
    clearInterval(ref.current); // interval পরিষ্কার করা হচ্ছে
  }
 
  let secondsPassed = 0;
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000;
  }
 
  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>Start</button>
      <button onClick={handleStop}>Stop</button>
    </>
  );
}

Differences Between refs and state (state এবং ref এর মধ্যে পার্থক্য)

RefsState
useRef শুরুতে একটি মান নেয় এবং একটি অবজেক্ট রিটার্ন করে যেখানে current নামের প্রপার্টিতে মান থাকেuseState একটি স্টেট ভ্যারিয়েবল ও setter function রিটার্ন করে
ভ্যালু পরিবর্তন হলেও useRef রি-রেন্ডার ট্রিগার করেনাভ্যালু আপডেট করলে রি-রেন্ডার ট্রিগার করে
useRef এর ভ্যালু কোনো setter function ছাড়াই পরিবর্তন করা যায়useState এর ভ্যালু setter function দিয়ে পরিবর্তন হয়
ref.current মান কম্পোনেন্ট রেন্ডারিং এ ব্যবহার করা যাবে নাস্টেটের মান সরাসরি UI তে ব্যবহার করা যায়

When to Use Ref (কখন ref ব্যবহার করা উচিত)

সাধারণত useRef কম ব্যবহৃত হয়। তবে যখন রিয়াক্টের কন্ট্রোলের বাইরে যেকোনো কিছু ব্যবহারের প্রয়োজন, যেমন ব্রাউজার API এর সঙ্গে কাজ, তখন useRef ব্যবহার করা উচিত।

  1. Timeout / Interval ID সংরক্ষণ করার জন্য
  2. DOM elements সংরক্ষণ এবং মডিফাই করার জন্য
  3. কোনো অবজেক্ট যা JSX এ দেখানোর প্রয়োজন নেই

Best Practices for Refs

  1. Treat refs as an escape hatch - ref কে এক্সটারনাল API এর জন্য ব্যবহার করুন।
  2. Don’t read or write ref.current during rendering - রেন্ডারিং এর সময় ref.current পড়া বা লেখা উচিত নয়।

On this page