State: A Component Memory

State: একটি কম্পোনেন্টের মেমোরি

React কম্পোনেন্টের state হল সেই মেমোরি যেখানে কম্পোনেন্টের ডাটা রাখা হয় এবং তা পরিবর্তন হতে পারে। উদাহরণস্বরূপ, একজন ইউজার যদি ফর্মে কিছু টাইপ করেন, ছবি স্লাইড করেন বা কোনো বাটনে ক্লিক করেন, তাহলে সেই ইন্টারঅ্যাকশন অনুযায়ী UI আপডেট হবে। এই পরিবর্তনগুলো state এর মাধ্যমে সম্ভব হয়।

React এর state হলো সেই মেমোরি যেখানে কম্পোনেন্টের current data রাখা হয়—যেমন ইনপুট ভ্যালু, ছবির নাম্বার, বা শপিং কার্টে থাকা প্রোডাক্ট।

State ব্যবহার কিভাবে করবেন?

React কম্পোনেন্টে state এড করতে useState হুক ব্যবহার করি। এটি দুটি জিনিস রিটার্ন করে:

  1. একটি state ভেরিয়েবল যা ১ম অবস্থায় আপনার ডাটা সংরক্ষণ করবে
  2. একটি সেটার ফাংশন যা ২য় অবস্থায় state ভেরিয়েবলির মান আপডেট করে এবং React কে জানায় যে- কম্পোনেন্টটি আবার রেন্ডার করতে হবে।

নিচের উদাহরণটি দেখুন যেখানে state ছাড়া কাজটি হবে না:

import { users } from "./users";
 
export default function App() {
  let index = 0;
 
  function handleClick() {
    index = index + 1; // index লুপ করবে
    console.log(index);
  }
 
  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-4">
      <div className="bg-white shadow-lg rounded-lg p-6 text-center">
        <img
          src={users[index].profilePic}
          alt={users[index].name}
          className="w-32 h-32 rounded-full mx-auto border-4 border-blue-500"
        />
        <h2 className="text-xl font-semibold mt-4">
          Name: {users[index].name}
        </h2>
        <p className="text-gray-600">Profile ID: {users[index].id}</p>
        <button
          onClick={handleClick}
          className="mt-4 px-6 py-2 bg-blue-500 text-white font-semibold rounded-lg hover:bg-blue-600 transition duration-300 cursor-pointer"
        >
          Next
        </button>
      </div>
    </div>
  );
}

যখন একটি রেগুলার Variable যথেষ্ট নয়

উপরের কোডে কম্পোনেন্টটি প্রোফাইল ইমেজ রেন্ডার করছে। "পরবর্তী" বাটনে ক্লিক করলে ইন্ডেক্সটি পরিবর্তন হয়ে পরবর্তী প্রোফাইল দেখানো কথা। কিন্তু, যখন আপনি কোডটি রান করবেন, দেখবেন যে এটি কাজ করবে না। কারণ, এখানে index একটি লোকাল রেগুলার ভেরিয়েবল। React জানে না যে UI আপডেট করা দরকার।

  • যখন বাটনে ক্লিক করো, index আপডেট হয় ঠিকই, কিন্তু React পরের বার নতুন করে পুরো কম্পোনেন্ট রেন্ডার করে, এবং তখন index আবার ০ থেকে শুরু হয়
  • তাই তুমি যতবার ক্লিক করো, index = 0 থেকে শুরু হয়, এবং UI তে কোনো পরিবর্তন দেখা যায় না।

কেন UI আপডেট হচ্ছে না? সহজ ব্যাখ্যা

এই সমস্যার কারণ দুটি:

1️⃣ প্রতি রেন্ডারে Local Variable এর মান আবার ০ থেকে শুরু হয়!
এখানে index নামের একটি লোকাল ভেরিয়েবল উদাহরণ হিসেবে ব্যবহার করা হয়েছে:

🔹 এখানে index একটি লোকাল ভেরিয়েবল।
🔹 যখন handleClick ফাংশন কল হয়, index আপডেট হয়, কিন্তু UI তে কোনো পরিবর্তন হয় না!

ধরো, তুমি Click Me বাটনে ক্লিক করলে index = 1 হয়, কিন্তু React কম্পোনেন্টটি আবার নতুন করে রেন্ডার করলে index আবার ০ থেকে শুরু হয়। তাই UI তে index বাড়তে দেখা যাবে না।


2️⃣ লোকাল ভেরিয়েবল পরিবর্তন হলে React তা বুঝতে পারে না, তাই কম্পোনেন্ট পুনরায় রেন্ডার করে না।

function Example() {
  let count = 0; // Local Variable
 
  function handleClick() {
    count = count + 1;
    console.log(count); // Console-এ মান পরিবর্তন হবে, কিন্তু UI আপডেট হবে না!
  }
 
  return <button onClick={handleClick}>Clicked {count} times</button>;
}

React UI আপডেট করে কেবল যদি State পরিবর্তন হয়।


সমাধান: useState হুকঃ একটি State Variable যোগ

এটি ঠিক করার জন্য useState হুক ব্যবহার করতে হবে। useState হুক React কে জানায় যে state টি পরিবর্তন হয়েছে, এবং সে অনুযায়ী UI পুনরায় রেন্ডার করো।

এখন আপনি যদি index এর পরিবর্তন state হিসেবে সংরক্ষণ করেন, তাহলে React সেই পরিবর্তনগুলো বুঝতে পারবে এবং UI আপডেট করে ফেলবে।


useState হুক ব্যবহার করে state যোগ করলে:

  • ১ম অবস্থায় স্টেট ভেরিয়েবলটি প্রাথমিক মানটি ধরে রাখবে
  • ২য় অবস্থায় সেটার ফাংশন দিয়ে যখন স্টেট ভেরিয়েবলের মান পরিবর্তন করে দেয়া হবে, React তখন UI আপডেট করবে।
import { useState } from "react";
 
function App() {
  const [index, setIndex] = useState(0); // state তৈরি করা হলো
 
  function handleClick() {
    setIndex(index + 1); // state পরিবর্তন হচ্ছে
  }
 
  return (
    <div>
      <img src={users[index].profilePic} alt={users[index].name} />
      <button onClick={handleClick}>Next</button>
    </div>
  );
}

এখানে setIndex ফাংশন ব্যবহার করে আপনি index পরিবর্তন করবেন এবং React তখন বুঝবে যে UI আবার রেন্ডার করতে হবে।


এইভাবে, React-এ state ব্যবহার করে আপনি কম্পোনেন্টের মেমোরিতে সেভ করে রাখতে পারেন এবং প্রয়োজনের মেমরির ডাটা পরিবর্তন করে UI আপডেট করতে পারেন।

React-এ তোমার প্রথম Hook: useState

React-এ useState এবং যে ফাংশনগুলো যা "use" দিয়ে শুরু হয়, তাকে React এ Hook বলা হয়।

Hook কী?

Hooks হলো বিশেষ ধরনের ফাংশন যা শুধুমাত্র React রেন্ডারিং করার জন্য কাজ করে। হুকগুলোর মাধ্যমে React-এর বিভিন্ন ফিচার ব্যবহার করা যায়।

এপ্লিকেশনের State ম্যানেজমেন্ট করা হলো Hooks-এর অন্যতম প্রধান কাজ, তবে React-এ আরও অনেক ধরনের Hook আছে, যেগুল আমরা পরবর্তীতে শিখবো।


গুরুত্বপূর্ণ সতর্কতা (Pitfall)

Hooks গুলো শুধুমাত্র কম্পোনেন্টের শীর্ষ স্তরে (top level)Import করা হয়।
আমরা (if else condition), লুপ (loop), বা নেস্টেড ফাংশনের (nested function) ভিতরে কোনো Hook লিখতে পারব না।

যেমনভাবে আমরা JavaScript ফাইলের শুরুতে import ব্যবহার করতে পারি, তেমনি React-এ Hooks সবসময় কম্পোনেন্টের শীর্ষে থাকতে হবে।


useState এর গঠন ও কাজ

When you call useState, you are telling React that you want this component to remember something:

React-এ useState ব্যবহার করে আমরা একটি state variable তৈরি করি, যা কম্পোনেন্টের মধ্যে কিছু তথ্য সংরক্ষণ করে এবং পরিবর্তন করতে সাহায্য করে।

🎯 উদাহরণ:

const [index, setIndex] = useState(0);

এই ক্ষেত্রে,

  • index হলো state variable, যা React মনে রাখবে।
  • setIndex হলো state setter function, যা state আপডেট করতে সাহায্য করে ও কম্পোনেন্ট আবার রেন্ডার করতে হেল্প করে।

👉 কিভাবে এটি কাজ করে?

  1. প্রথমবার রেন্ডার:
  • কম্পোনেন্ট প্রথমবার রেন্ডার হলে, useState(0) কল করলে React [0, setIndex] রিটার্ন করে।
  • অর্থাৎ, index-এর প্রাথমিক মান ০ সেট হয়।
  1. State আপডেট:
  • যখন ইউজার বাটনে ক্লিক করে, তখন setIndex(index + 1) কল হয়।
  • ধরো, index এর মান ০ ছিল, তাহলে setIndex(1) হবে।
  • React মনে রাখবে যে index এখন ১ হয়েছে এবং নতুন রেন্ডার ট্রিগার করবে।
  1. React আবার রেন্ডার করবে:
  • দ্বিতীয়বার কম্পোনেন্ট রেন্ডার হলে, React এখনও useState(0) দেখে,
  • কিন্তু আগের state মনে রাখার কারণে এবার [1, setIndex] রিটার্ন করে।

🔄 এভাবেই প্রতিবার state পরিবর্তন হলে React নতুন মান মনে রাখে এবং কম্পোনেন্টকে নতুনভাবে রেন্ডার করে।


** গুরুত্বপূর্ণ টিপস:**

useState এর নামকরণের জন্য সাধারণ কনভেনশন হলো:

const [something, setSomething] = useState(initialValue);

যেমন:

  • [count, setCount]
  • [name, setName]
  • [isLoggedIn, setIsLoggedIn]

এটি অনুসরণ করলে কোড পরিষ্কার এবং বুঝতে সহজ হবে।


React-এ useState হলো সবচেয়ে গুরুত্বপূর্ণ Hook, যা কম্পোনেন্টকে ডাটা মেমোরাইজ করতে ও পরিবর্তন করতে সাহায্য করে।

একটি কম্পোনেন্টে একাধিক স্টেট ভেরিয়েবল ব্যবহারের সুবিধা

React-এ আপনি একটি কম্পোনেন্টের মধ্যে একাধিক স্টেট ভেরিয়েবল রাখতে পারেন, এবং এগুলো বিভিন্ন ধরণের হতে পারে। নিচের উদাহরণে, একটি Gallery কম্পোনেন্ট আছে যেখানে দুটি স্টেট ভেরিয়েবল ব্যবহার করা হয়েছে:

  • index: এটি বর্তমান ভাস্কর্যের ছবির অবস্থান (নাম্বার) সংরক্ষণ করে।
  • showMore: এটি একটি বুলিয়ান মান দিয়ে নির্ধারণ করা হয়, যে বিস্তারিত তথ্য দেখানো হবে কি না?

উদাহরণ কোড:

import { useState } from "react";
import { sculptureList } from "./data.js";
 
export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);
 
  function handleNextClick() {
    setIndex(index + 1);
  }
 
  function handleMoreClick() {
    setShowMore(!showMore);
  }
 
  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>Next</button>
      <h2>
        <i>{sculpture.name} </i>
        by {sculpture.artist}
      </h2>
      <h3>
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? "Hide" : "Show"} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img src={sculpture.url} alt={sculpture.alt} />
    </>
  );
}

কখন একাধিক স্টেট ব্যবহার করবেন?

যদি দুটি স্টেট একে অপরের সাথে সম্পর্কিত না হয়, তাহলে আলাদা স্টেট ভেরিয়েবল ব্যবহার করাই ভালো। যেমন এই উদাহরণে index এবং showMore একে অপরের উপর নির্ভরশীল নয়, তাই আলাদা স্টেট হিসেবে রাখা হয়েছে।

তবে, যদি স্টেট পরিবর্তনগুলি একসাথে ঘটে, তাহলে একাধিক স্টেট ভেরিয়েবল ব্যবহারের পরিবর্তে একটি অবজেক্ট হিসেবে রাখা সুবিধাজনক হতে পারে। উদাহরণস্বরূপ, ফর্মের ক্ষেত্রে প্রতিটি ইনপুট ফিল্ডের জন্য আলাদা স্টেট রাখার পরিবর্তে একটি অবজেক্টে সব ফিল্ড ধরে রাখা সহজ হতে পারে।

স্টেট সম্পূর্ণ বিচ্ছিন্ন এবং ব্যক্তিগত (State is Isolated and Private)

React-এ state হলো প্রত্যেক component-এর নিজের ডাটা, যা শুধু ঐ component-এর ভেতরেই থাকে। যদি আপনি একই component UI এ একাধিকবার ব্যবহার করেন, তাহলে প্রতিটি component-এর state বিচ্ছিন্ন থাকব, অর্থাৎ একটিতে পরিবর্তন করলে অন্যটিতে কোনো প্রভাব পড়বে না।

উদাহরণ:

নিচের কোডে আমরা Gallery নামের একটি component দুইবার ব্যবহার করেছি—

import Gallery from "./Gallery.js";
 
export default function Page() {
  return (
    <div className="Page">
      <Gallery />
      <Gallery />
    </div>
  );
}

এখন, যদি আপনি প্রথম Gallery-তে ক্লিক করেন, এটি আপডেট হবে, কিন্তু দ্বিতীয় Gallery একই থাকবে।

কেন এমন হয়?

React-এর state সাধারণ ভেরিয়েবলের মতো কাজ করে না। সাধারণ ভেরিয়েবল হলে, এক জায়গায় পরিবর্তন করলে সব জায়গায় প্রভাব পড়ত। কিন্তু state প্রতিটি component-এর জন্য আলাদা থাকে।

এখানে দুটি Gallery আলাদা আলাদা state নিয়ে কাজ করছে, তাই একটির state পরিবর্তন করলেও অন্যটি অপরিবর্তিত থাকবে।


Component Instance কী?

একটি component ব্যবহার করলেই সেটির একটি নতুন কপি (instance) তৈরি হয়। যেমন, উপরের উদাহরণে Gallery component দুইবার ব্যবহার করা হয়েছে, তাই React দুটি আলাদা instance তৈরি করেছে। প্রতিটি instance-এর state আলাদা থাকে, তাই একটির পরিবর্তন অন্যটিকে প্রভাবিত করে না।

সহজ ভাষায় বললে:
একটি component = একটি ডিজাইন (template)
একটি instance = সেই ডিজাইনের একটি আলাদা কপি

যেমন,

  • একটি ফর্ম component বানালে, যদি সেটি একাধিকবার render করা হয়, প্রতিটি ফর্ম আলাদা থাকবে।
  • একটি টাস্ক লিস্ট component বানালে, প্রতিটি টাস্ক আইটেম আলাদা হবে।

যদি দুইটি Gallery একসাথে পরিবর্তন করতে চান?

যদি চান দুইটি Gallery একসাথে পরিবর্তিত হোক, তাহলে state child component থেকে parent component-এ নিয়ে আসতে হবে।

এটাকে বলে Lifting State Up, যা React-এ state শেয়ার করার নিয়ম।

রিক্যাপ (Recap)

  1. State ভেরিয়েবল ব্যবহার করুন: যখন একটি component কে "মনে রাখতে" হবে কিছু তথ্য render-গুলোর মধ্যে, তখন state ভেরিয়েবল ব্যবহার করুন।

  2. State ভেরিয়েবল ঘোষণা করা হয় useState Hook ব্যবহার করে: state ভেরিয়েবল ঘোষণা করার জন্য useState Hook কল করতে হয়।

  3. Hooks কী? Hooks হল বিশেষ ফাংশন যেগুলো use দিয়ে শুরু হয়। এগুলো আপনাকে React-এর ফিচারগুলোর সাথে "hook into" করতে দেয়, যেমন state।

  4. Hooks এর শর্ত: Hooks আমদানি (imports)-এর মতো মনে হতে পারে: এগুলো শর্তসাপেক্ষে কল করা যাবে না। useState সহ সমস্ত Hooks কেবল একটি component-এর উপরের স্তরে বা অন্য কোনো Hook-এর ভিতরে কল করা বৈধ।

  5. useState Hook কী ফেরত দেয়: useState Hook দুটি মান ফেরত দেয়: বর্তমান state এবং এটি আপডেট করার ফাংশন।

  6. একাধিক state ভেরিয়েবল থাকতে পারে: React অভ্যন্তরীণভাবে এগুলিকে তাদের ক্রম দ্বারা মিলিয়ে দেয়।

  7. State component-এর private: যদি আপনি একটি component দুটি স্থানে render করেন, প্রতিটি কপি নিজস্ব state পাবে।

💡 শেখার সুযোগ!

আমার কাছে HTML, CSS, Tailwind CSS, JavaScript, React, Git and Github শিখতে নিচের WhatsApp নাম্বারে যোগাযোগ কর।

মাসিক ২৫০০ টাকা নিব, সপ্তাহে ৩ দিন ক্লাস করাব।

কোর্স ডিউরেশন ৩ মাস। এটি একদম বিগিনারদের জন্য।

📞 WhatsApp এ যোগাযোগ করো