Queuing A Seris of State Update

স্টেট আপডেটের সিরিজকে কিউ করা

স্টেট ভেরিয়েবল সেট করা মানে হল- পরবর্তী রেন্ডারের জন্য এটি কিউ তৈরি করা। কিন্তু কখনও কখনও আপনি পরবর্তী রেন্ডারের আগের মানের উপর একাধিক অপারেশন করতে চান। এটি করতে, আপনাকে বুঝতে হবে কীভাবে React স্টেট আপডেটগুলিকে ব্যাচ করে।

এই পাঠে আপনি যা শিখবেন

  • "ব্যাচিং" কী এবং React কীভাবে এটি ব্যবহার করে একাধিক স্টেট আপডেট প্রসেস করে।
  • কীভাবে একই স্টেট ভেরিয়েবলে একাধিক আপডেট প্রয়োগ করতে হয়।
import { useState } from "react";
 
export default function Counter() {
  const [number, setNumber] = useState(0);
 
  return (
    <>
      <h1>{number}</h1>
      <button
        onClick={() => {
          setNumber(number + 1);
          setNumber(number + 1);
          setNumber(number + 1);
        }}
      >
        +3
      </button>
    </>
  );
}

তবে, আপনি আগের সেকশন থেকে মনে করতে পারেন, প্রতিটি রেন্ডারের স্টেট মান স্থির থাকে, তাই প্রথম রেন্ডারের ইভেন্ট হ্যান্ডলারের মধ্যে number এর মান সর্বদা ০, যতবারই আপনি setNumber(1) কল করুন না কেন:

setNumber(0 + 1);
setNumber(0 + 1);
setNumber(0 + 1);

কিন্তু এখানে একটি অন্য বিষয় কাজ করছে। React আপনার ইভেন্ট হ্যান্ডলারগুলিতে সব কোড চালানো পর্যন্ত অপেক্ষা করে স্টেট আপডেটগুলি প্রক্রিয়া করে। এই কারণে রি-রেন্ডার শুধুমাত্র এই সমস্ত setNumber() কলগুলির পরে ঘটে।

এটি আপনাকে রেস্টুরেন্টে একজন ওয়েটারের অর্ডার নেওয়ার কথা মনে করিয়ে দিতে পারে। একজন ওয়েটার আপনার প্রথম ডিশের উল্লেখে রান্নাঘরে দৌড়ায় না! বরং, তারা আপনাকে অর্ডার শেষ করতে দেয়, আপনাকে এতে পরিবর্তন করতে দেয় এবং এমনকি টেবিলের অন্য লোকদের থেকেও অর্ডার নেয়।

একজন মার্জিত ওয়েটার রেস্টুরেন্টে অর্ডার একাধিকবার নেয়, আর React ওয়েটারের ভূমিকা পালন করে। যখন তিনি setState() একাধিকবার কল করেন, তখন ওয়েটার শেষ যেটি তিনি অনুরোধ করেছিলেন সেটি তার চূড়ান্ত অর্ডার হিসেবে লিখে রাখে।

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

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

ব্যাচিং কি

এখানে ব্যাচিং মানে হলো রি-এক্ট কম্পোনেন্ট যাতে বার রিরেন্ডার না হয়, এই জন্য একবারে সব কাজগুলো নেয়ার পর কি কি কাজ করতে হবে এগুলো ব্যাচিং করে নেয়। তারপর ইউ আই এ একবারে রি-রেন্ডার করে।

পরবর্তী রেন্ডারের আগে একই স্টেট একাধিকবার আপডেট করা

এটি একটি অস্বাভাবিক ব্যবহার কেস, তবে আপনি যদি পরবর্তী রেন্ডারের আগে একই স্টেট ভেরিয়েবল একাধিকবার আপডেট করতে চান, setNumber(number + 1) এর মতো পরবর্তী স্টেট মান পাস করার পরিবর্তে, আপনি একটি ফাংশন পাস করতে পারেন যা পূর্ববর্তী কিউর স্টেটের উপর ভিত্তি করে পরবর্তী স্টেট গণনা করে, যেমন setNumber(n => n + 1)। এটি React কে "স্টেট মানের সাথে কিছু করার" জন্য বলতে একটি উপায়, কেবল এটিকে প্রতিস্থাপন করার পরিবর্তে।

এখন কাউন্টার বাড়ানোর চেষ্টা করুন:

import { useState } from "react";
 
export default function Counter() {
  const [number, setNumber] = useState(0);
 
  return (
    <>
      <h1>{number}</h1>
      <button
        onClick={() => {
          setNumber((n) => n + 1);
          setNumber((n) => n + 1);
          setNumber((n) => n + 1);
        }}
      >
        +3
      </button>
    </>
  );
}

এখানে, n => n + 1 একটি আপডেটার ফাংশন। যখন আপনি এটি একটি স্টেট সেটারে পাস করেন:

  • React এই ফাংশনটি কিউ করার জন্য যুক্ত করে যাতে ইভেন্ট হ্যান্ডলারের সমস্ত কোড চালানোর পর এটি প্রক্রিয়া করা হয়।
  • পরবর্তী রেন্ডারের সময়, React কিউটির মধ্য দিয়ে যায় এবং আপনাকে চূড়ান্ত আপডেট করা স্টেট প্রদান করে।
setNumber((n) => n + 1);
setNumber((n) => n + 1);
setNumber((n) => n + 1);

React ইভেন্ট হ্যান্ডলার চালানোর সময় এই লাইনগুলির মাধ্যমে কাজ করে:

  • setNumber(n => n + 1): n => n + 1 একটি ফাংশন। React এটি একটি কিউতে যোগ করে।
  • setNumber(n => n + 1): n => n + 1 একটি ফাংশন। React এটি একটি কিউতে যোগ করে।
  • setNumber(n => n + 1): n => n + 1 একটি ফাংশন। React এটি একটি কিউতে যোগ করে।

যখন আপনি পরবর্তী রেন্ডারের সময় useState কল করেন, React কিউটির মধ্য দিয়ে যায়। পূর্বের number স্টেট ০ ছিল, তাই React এটিকে প্রথম আপডেটার ফাংশনে n আর্গুমেন্ট হিসেবে পাস করে। এরপর React আপনার পূর্ববর্তী আপডেটার ফাংশনের রিটার্ন মানটি নেয় এবং পরবর্তী আপডেটারে n হিসেবে পাস করে, এবং এভাবে এটি চলতে থাকে:

কিউ করা আপডেটের মাধ্যমে React কাজ করার উপায়:

queued update	n	returns
n => n + 1	0	0 + 1 = 1
n => n + 1	1	1 + 1 = 2
n => n + 1	2	2 + 1 = 3

React ৩ কে চূড়ান্ত ফলাফল হিসেবে সংরক্ষণ করে এবং এটি useState থেকে রিটার্ন করে।

এ কারণেই উপরের উদাহরণে "+3" ক্লিক করা মানটি সঠিকভাবে ৩ দ্বারা বাড়িয়ে দেয়।

What happens if you update state after replacing it

এই ইভেন্ট হ্যান্ডেলারটি দেখো? তুমি কি ভাবছো পরবর্তী রেন্ডারে কোন নাম্বারটি UI তে শো করবে?

<button onClick={() => {
  setNumber(number + 5);
  setNumber(n => n + 1);
}}>

ইভেন্ট হ্যান্ডেলারটি রিএক্ট কে যা বলবে,

  1. setNumber(number + 5): number is 0, so setNumber(0 + 5). React adds “replace with 5” to its queue.
  2. setNumber(n => n + 1): n => n + 1 is an updater function. React adds that function to its queue.

React stores 6 as the final result and returns it from useState.

নোটঃ তুমি এখানে লক্ষ্য কর যে, setNumber(5) কাজ করছে এইভাবে setNumber(n => 5) but এখানে n is unused.

What happens if you replace state after updating it

Let’s try one more example. What do you think number will be in the next render?

  setNumber(number + 5);
  setNumber(n => n + 1);
  setNumber(42);
}}>```

Then React stores 42 as the final result and returns it from useState.

To summarize, here’s how you can think of what you’re passing to the setNumber state setter:

  1. An updater function (e.g. n => n + 1) এর আগে setState কল করলে- এই আপডেটার ফাংশন পূর্বের ভেলুটা ধরবে রেন্ডার না হয়েও এবং কিউতে এড করবে।
  2. Any other value (e.g. number 5) adds “replace with 5” to the queue, ignoring what’s already queued.

event handler গুলো এক্সিকিউট হওয়ার পর, React will trigger a re-render. During the re-render, React will process the queue. Updater functions run during rendering, so updater functions must be pure and only return the result. Don’t try to set state from inside of them or run other side effects. In Strict Mode, React will run each updater function twice (but discard the second result) to help you find mistakes.

Naming conventions

It’s common to name the updater function argument by the first letters of the corresponding state variable:

setEnabled((e) => !e);
setLastName((ln) => ln.reverse());
setFriendCount((fc) => fc * 2);

If you prefer more verbose code, another common convention is to repeat the full state variable name, like setEnabled(enabled => !enabled), or to use a prefix like setEnabled(prevEnabled => !prevEnabled).

Treat state as read-only

In other words, you should treat any JavaScript object that you put into state as read-only.

This example holds an object in state to represent the current pointer position. The red dot is supposed to move when you touch or move the cursor over the preview area. But the dot stays in the initial position: