ইউজারের ইনপুট অনুযায়ী UI পরিবর্তনের জন্য React-এ State ব্যবহার

ইউজারের ইনপুট অনুযায়ী UI পরিবর্তনের জন্য React-এ State ব্যবহার

React, UI ম্যানেজ করে Declarative পদ্ধতিতে। DOM-এর প্রতিটি অংশ আলাদা করে ম্যানিপুলেট না করে, আপনি শুধু কম্পোনেন্টের বিভিন্ন স্টেট (যেমন: শুরু, টাইপিং, সাবমিট) বর্ণনা করবেন। প্রতিটি স্টেট অনুযায়ী কী UI দেখানো হবে, সেটাই React-কে বলে দিবেন। এরপর React নিজেই ঠিক করবে, কখন কী দেখাতে হবে। যেমন ধরুন: “যদি ইউজার টাইপ করে, তাহলে বাটন disable false কর।” এইভাবে কাজ করার পদ্ধতি ডিজাইনারদের ভাবনার সাথে মিল রাখে, কারণ তারাও সাধারণত UI-র বিভিন্ন অবস্থা কল্পনা করেই ডিজাইন করে।

আপনি শিখবেন:

  • Declarative UI প্রোগ্রামিং কিভাবে Imperative UI প্রোগ্রামিং থেকে ভিন্ন
  • আপনার কম্পোনেন্ট কত রকম ভিজ্যুয়াল স্টেটে থাকতে পারে, তা কীভাবে ঠিক করতে হয়
  • কোডে কীভাবে এক ভিজ্যুয়াল স্টেট থেকে কিভাবে আরেক ভিজ্যুয়াল স্টেটে যেতে হয় (trigger করতে হয়)

Declarative UI বনাম Imperative UI এর তুলনা

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

  • আপনি যখন ফর্মে কিছু টাইপ করেন, "জমা দিন" এই বাটনটি সক্রিয় হয়ে যায়।
  • আপনি যখন "জমা দিন" বাটনে ক্লিক করেন, তখন ফর্ম এবং বাটন উভয়ই disable হয়ে যায় এবং একটি স্পিনার লোডিং প্রদর্শিত হয়।
  • যদি আপনার উত্তর সফল হয়, তাহলে ফর্মটি hidden হয়ে যায় এবং "ধন্যবাদ" মেসেজ প্রদর্শিত হয়।
  • যদি আপনার উত্তর ভুল হয়, তাহলে একটি ত্রুটির মেসেজ প্রদর্শিত হয় এবং ফর্মটি আবার সক্রিয় হয়ে যায়।

Imperative Programming-এ, উপরের উদাহরণে আপনি ইন্টারঅ্যাকশন কীভাবে বাস্তবায়ন করেন তার স্টেপ বাই স্টেপ একটি নির্দেশনা। কল্পনা করুন- আপনি একটি গাড়িতে করে কারো সাথে যাচ্ছেন এবং তাদেরকে ধাপে ধাপে নির্দেশনা দিচ্ছেন কোথায় যেতে হবে।

ড্রাইভার (JS) জানে না আপনি কোথায় যেতে চান, তারা শুধু আপনার প্রত্যেক নির্দেশ অনুসরণ করে। (আর যদি আপনি ভুল নির্দেশনা দেন, তাহলে আপনি ভুল জায়গায় পৌঁছে যাবেন!) একে আদেশমূলক বলা হয় কারণ আপনাকে শুরু থেকে শেষ পর্যন্ত প্রতিটি উপাদানকে আপডেট করার জন্য 'আদেশ' করতে হবে, কম্পিউটারকে বলতে হবে কীভাবে ইউআই আপডেট করতে হবে।

এই উদাহরণে, ফর্মটি React ছাড়াই তৈরি করা হয়েছে। এটি শুধুমাত্র ব্রাউজার DOM ব্যবহার করে:

let form = document.getElementById("form");
let textarea = document.getElementById("textarea");
let button = document.getElementById("button");
let loadingMessage = document.getElementById("loading");
let errorMessage = document.getElementById("error");
let successMessage = document.getElementById("success");
form.onsubmit = handleFormSubmit;
textarea.oninput = handleTextareaChange;
 
async function handleFormSubmit(e) {
  e.preventDefault();
  disable(textarea);
  disable(button);
  show(loadingMessage);
  hide(errorMessage);
  try {
    await submitForm(textarea.value);
    show(successMessage);
    hide(form);
  } catch (err) {
    show(errorMessage);
    errorMessage.textContent = err.message;
  } finally {
    hide(loadingMessage);
    enable(textarea);
    enable(button);
  }
}
 
function handleTextareaChange() {
  if (textarea.value.length === 0) {
    disable(button);
  } else {
    enable(button);
  }
}
 
function hide(el) {
  el.style.display = "none";
}
 
function show(el) {
  el.style.display = "";
}
 
function enable(el) {
  el.disabled = false;
}
 
function disable(el) {
  el.disabled = true;
}
 
function submitForm(answer) {
  // Pretend it's hitting the network.
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (answer.toLowerCase() === "istanbul") {
        resolve();
      } else {
        reject(new Error("Good guess but a wrong answer. Try again!"));
      }
    }, 1500);
  });
}

জটিল সিস্টেমের জন্য সমস্যা:

"বিচ্ছিন্ন উদাহরণের জন্য আদেশমূলকভাবে UI কে পরিচালনা করা যথেষ্ট ভালো কাজ করে, কিন্তু জটিল সিস্টেমে এটি দিয়ে ম্যানেজ করা অত্যন্ত কঠিন হয়ে পড়ে। এই ধরনের বিভিন্ন ফর্ম পুরো একটি পেজে ম্যানেজ/আপডেট করার কথা কল্পনা করুন। একটি নতুন UI উপাদান বা একটি নতুন ইন্টারঅ্যাকশন যোগ করতে হলে নিশ্চিত হতে হবে যে আপনি কোনো বাগ তৈরি করেননি (উদাহরণস্বরূপ, কিছু দেখাতে বা লুকাতে ভুলে যাওয়া)।"

React-এর সমাধান:

রিঅ্যাক্টে কাজ করার জন্য, আপনি কিভাবে Declaratively চিন্তা করবেন তা আরও ভালোভাবে বুঝতে, নিচের পদক্ষেপগুলি অনুসরণ করুন:

Step 1: আপনার UI এর বিভিন্ন দৃশ্যমান অবস্থার স্ক্রিনশর্ট নিন:

যেমন একটি ফর্মের বিভিন্ন অবস্থা কি কি হতে পারে তা নির্ধারণ করুন- যেমন একটি ফর্ম খালি থাকা অবস্থা, ফিল আপ শুরু করা অবস্থা, ফিল আপ সাবমিট করা অবস্থা, ফিল আপ সাবমিট শেষে রিকুয়েস্ট সফল বা ব্যর্থ হওয়ার পরের অবস্থা।

UI এর বিভিন্ন অবস্থার স্ক্রিনশর্ট:

All Screenshot of your UI

Step 2: কোন ঘটনাগুলোর জন্য স্টেট পরিবর্তন হবে সেটা ঠিক করো

React অ্যাপ্লিকেশনে UI-তে পরিবর্তন আনা হয় state ব্যবহার করে। স্টেট পরিবর্তন দুই ধরণের ইনপুট থেকে ট্রিগার হতে পারে:


১. Human Inputs (মানুষের ইনপুট):

এগুলো হলো ব্যবহারকারীর সরাসরি ইন্টার‌্যাকশন, যেমনঃ

  • একটি বাটনে প্রেস করা
  • একটি ফিল্ডে টাইপ করা
  • একটি লিঙ্কে ক্লিক করা

উদাহরণ: যখন একজন ব্যবহারকারী একটি টেক্সট ফিল্ডে টাইপ করেন, তখন স্টেট পরিবর্তিত হয়।


২. Computer Inputs (সিস্টেম বা কম্পিউটারের ইনপুট):

এগুলো হলো সিস্টেম থেকে আসা নির্দিষ্ট ইভেন্ট, যেমনঃ

  • সার্ভার থেকে একটি নেটওয়ার্ক রেসপন্স আসা
  • একটি টাইমআউট শেষ হওয়া
  • একটি ইমেজ সম্পূর্ণ লোড হওয়া

উদাহরণ:

যখন সার্ভার একটি সফল রেসপন্স পাঠায়, তখন স্টেট পরিবর্তিত হয় এবং UI আপডেট হয়।


উদাহরণ: একটি ফর্মের স্টেট পরিবর্তনের ধাপ

আপনার ফর্মে স্টেট পরিবর্তন করার জন্য নিচের ইনপুটগুলো বিবেচনা করতে হবে:

  1. Changing the text input (Human Input):

    • টেক্সট ইনপুটে টাইপ করা শুরু করলে স্টেট Empty থেকে Typing-এ পরিবর্তিত হবে।
    • যদি টেক্সট ইনপুট খালি হয়, এটি আবার Typing থেকে Empty-তে ফিরে যাবে।
  2. Clicking the Submit button (Human Input):

    • সাবমিট বাটনে ক্লিক করলে স্টেট Submitting-এ পরিবর্তিত হবে।
  3. Successful network response (Computer Input):

    • সার্ভার থেকে সফল রেসপন্স এলে স্টেট Success-এ পরিবর্তিত হবে।
  4. Failed network response (Computer Input):

    • যদি রেসপন্স ব্যর্থ হয়, স্টেট Error-এ পরিবর্তিত হবে এবং এর সাথে নির্দিষ্ট ত্রুটি বার্তা যোগ হবে।

গুরুত্বপূর্ণ: Human Inputs এর জন্য Event Handlers দরকার!

মানুষের ইনপুটগুলো ধরার জন্য আমরা React-এর event handlers (যেমনঃ onClick, onChange) ব্যবহার করব।


ভিজ্যুয়ালাইজেশন: Flow Diagram

স্টেট পরিবর্তনের ফ্লো বোঝার জন্য, একটি ফ্লো চার্ট তৈরি করুন:

  1. প্রতিটি স্টেটকে একটি বৃত্ত হিসেবে আঁকুন।
  2. প্রতিটি স্টেট পরিবর্তনকে একটি তীর হিসেবে চিহ্নিত করুন।
  3. তীরগুলোতে ট্রিগার ইভেন্টের নাম লিখুন (যেমনঃ start typing, press submit, network error)।

উদাহরণ ফ্লো চার্ট:

  1. Empty → Typing → Submitting → Success/Error

    • শুরু: ফর্মটি খালি এবং "জমা দিন" বাটনটি নিষ্ক্রিয়।
    • টাইপিং: ইউজার কিছু টাইপ করছে এবং "জমা দিন" বাটনটি সক্রিয়।
    • সাবমিট করা হয়েছে: ইউজার "জমা দিন" বাটনে ক্লিক করেছে এবং ফর্মটি লোডিং অবস্থায় রয়েছে।
    • সফল: ইউজার সঠিক উত্তর জমা দিয়েছে এবং "ধন্যবাদ" মেসেজ দেখাচ্ছে।
    • ত্রুটি: ইউজার ভুল উত্তর জমা দিয়েছে এবং একটি ত্রুটির মেসেজ দেখাচ্ছে।

এটি শিখলে আপনি React স্টেট ম্যানেজমেন্টে আরও ভালোভাবে দক্ষ হবেন।

Step 3: useState দিয়ে মেমরিতে State রাখুন:

React-এ স্টেট হলো আপনার কম্পোনেন্টের "moving piece," যা UI এর পরিবর্তনের জন্য দায়ী। এখানে (simplicity) সবচেয়ে গুরুত্বপূর্ণ। কম স্টেট ব্যবহার করলে বাগ কম হবে এবং কোড সহজে মেইনটেইন করা যাবে।


প্রাথমিক ভাবে স্টেট নির্ধারণ করুন

প্রথমে আপনার কম্পোনেন্টে এমন স্টেট ব্যবহার করুন যা মাস্ট লাগবেই। উদাহরণস্বরূপ:

  1. ইনপুটের উত্তর (answer): ব্যবহারকারীর ইনপুট স্টোর করার জন্য।
  2. ত্রুটি (error): শেষ ত্রুটি স্টোর করার জন্য (যদি থাকে)।
const [answer, setAnswer] = useState(""); // ব্যবহারকারীর ইনপুট স্টোর করে
const [error, setError] = useState(null); // ত্রুটি স্টোর করে

ভিজ্যুয়াল স্টেট রেপ্রেজেন্ট করুন

আপনার কম্পোনেন্টের বিভিন্ন ভিজ্যুয়াল স্টেট ম্যানেজ করতে অতিরিক্ত স্টেট ভ্যারিয়েবল প্রয়োজন হবে। উদাহরণস্বরূপ:

  • ফর্ম খালি থাকলে isEmpty হবে true
  • টাইপ শুরু করলে isTyping হবে true
  • সাবমিট করলে isSubmitting হবে true
  • সফল উত্তর পেলে isSuccess হবে true
  • কোনো ত্রুটি হলে isError হবে true
const [isEmpty, setIsEmpty] = useState(true);
const [isTyping, setIsTyping] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [isError, setIsError] = useState(false);

স্টেট রিফ্যাক্টর করা (Refactoring State)

যদিও উপরের পদ্ধতি কাজ করবে, এটি কিছুটা জটিল হতে পারে কারণ প্রতিটি স্টেট আলাদাভাবে ম্যানেজ করতে হবে। একটি সহজ সমাধান হচ্ছে একটি একক ভ্যারিয়েবল ব্যবহার করা যা সব ভিজ্যুয়াল স্টেট রেপ্রেজেন্ট করে:

const [status, setStatus] = useState("empty");
// সম্ভাব্য মান: 'empty', 'typing', 'submitting', 'success', 'error'

কেন এটি ভালো:

  • সহজ কোড: কম স্টেট ভ্যারিয়েবল।
  • স্টেট ট্রানজিশন পরিষ্কার: শুধু status আপডেট করলেই ভিজ্যুয়াল স্টেট পরিবর্তিত হয়।

ব্যবহার:

if (status === "empty") {
  // খালি ফর্ম রেন্ডার করুন
} else if (status === "typing") {
  // টাইপিং স্টেট রেন্ডার করুন
} else if (status === "submitting") {
  // সাবমিটিং স্টেট রেন্ডার করুন
} else if (status === "success") {
  // সফল স্টেট রেন্ডার করুন
} else if (status === "error") {
  // ত্রুটির স্টেট রেন্ডার করুন
}

এবং উন্নতি করুন

স্টেট ব্যবস্থাপনার জন্য আপনার প্রথম ধারণাটি হয়তো সেরা হবে না। কিন্তু এটি সমস্যা নয়—স্টেট রিফ্যাক্টর করা React ডেভেলপমেন্টের একটি স্বাভাবিক অংশ!

কৌশল:

  1. সহজ থেকে শুরু করুন: একদম প্রয়োজনীয় স্টেট দিয়ে কাজ শুরু করুন।
  2. সমস্ত ভিজ্যুয়াল স্টেট কাভার করুন: নিশ্চিত করুন প্রতিটি ভিজ্যুয়াল স্টেট ম্যানেজ করা হচ্ছে।
  3. পুনরায় চিন্তা করুন: যেকোনো জটিলতা দূর করতে স্টেট রিফ্যাক্টর করুন।

এই পদ্ধতিতে কাজ করলে আপনার কোড সহজ হবে এবং React-এ স্টেট ম্যানেজমেন্টে দক্ষতা বাড়বে!

Step 4: অপ্রয়োজনীয় অবস্থার ভেরিয়েবলগুলি সরিয়ে দিন:

আপনার UI এর অবস্থার পরিবর্তনগুলো কেবল প্রয়োজনীয়গুলি রাখুন। অতিরিক্ত স্টেট নিবেন না। অপ্রয়োজনীয়গুলি স্টেটগুলো অপসারণ করুন, কারণ এগুলি আপনার কোডকে আরও জটিল করে তুলবে।

Step 5: UI এর অবস্থাগুলো সেট করার জন্য event handler ব্যবহার করুন

isTyping এ onChange এ button visible করা, ইত্যাদি যে ঘটনাগুলি ঘটলে আপনার UI এর পরিবর্তনশীল ভেরিয়েবলের মানগুলো আপডেট করতে ইভেন্ট হ্যান্ডলার লাগবে।

এই পদক্ষেপগুলি অনুসরণ করে, আপনি আপনার ফর্মকে একটি ঘোষণামূলক পদ্ধতিতে React দিয়ে কাজ করাতে পারেন।