State mutation-এর ভয় করতে হবে জয়...
Tags: react, javascript, programming, webdev
Published: 2024-01-16 18:34:25


![state mutation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipv7rhc2kfidnrntmt8p.png)
<heading>
## ডেটা কি এবং জাভাস্ক্রিপ্টের ডেটা টাইপ কি কি?
</heading>
<main>
 **ডেটা** হলো তথ্যের সংগ্রহণ, সংরক্ষণ এবং প্রক্রিয়া করার জন্য ব্যবহৃত ইনফরমেশন বা তথ্য। জাভাস্ক্রিপ্টে বিভিন্ন ধরনের ডেটা টাইপ রয়েছে। যেমন:-
 
 - **প্রিমিটিভ টাইপস (Primitive Types):**
     - **স্ট্রিং (String):** এটি টেক্সট ডেটা রাখতে ব্যবহৃত হয়, উদাহরণস্বরূপ: `"Hello World"`.
     - **নাম্বার (Number):** এটি সংখ্যা ডেটা রাখতে ব্যবহৃত হয়, উদাহরণস্বরূপ: `42`, `3.14`.
     - **বুলিয়ান (Boolean):** এটি সত্য বা মিথ্যা স্টেটমেন্ট রাখতে ব্যবহৃত হয়, উদাহরণস্বরূপ: `true` বা `false`.
 - **রেফারেন্স টাইপস (Reference Types):**
     - **অবজেক্ট (Object):** এটি ডেটা কলেকশন ধারণ করতে ব্যবহৃত হয় এবং এটি প্রপার্টি এবং মেথড ধারণ করতে পারে। উদাহরণস্বরূপ: `{ name: "John", age: 25 }`.
     - **অ্যারে (Array):** এটি একটি একই ধরনের ডেটা তালিকা ধারণ করতে ব্যবহৃত হয়। উদাহরণস্বরূপ: `[1, 2, 3, 4, 5]`.
     - **ফাংশন (Function):** এটি একটি নির্দিষ্ট কাজ বা অপারেশন করতে ব্যবহৃত হয় এবং এটি একটি ভ্যালু রিটার্ন করতে পারে। উদাহরণস্বরূপ: 

```js
function addNumbers(a, b) { return a + b;}
```
 
     
 - **স্পেশাল রেফারেন্স টাইপস (Special Reference Types):**
     - **নাল (Null):** এটি একটি খালি মান রাখতে ব্যবহৃত হয়, উদাহরণস্বরূপ: `null`.
     - **অনডিফাইন্ড (Undefined):** একটি ভেরিয়েবল ডিক্লেয়ার হওয়ার পর এর কোনো মান দেওয়া হয়নি।।
 
 এই টাইপগুলি মিলে একটি জাভাস্ক্রিপ্ট অ্যাপ্লিকেশন তৈরি হয়। এছাড়া, জাভাস্ক্রিপ্টে ইউজার-ডিফাইনড (User-Defined) ক্লাস বা কাস্টম টাইপগুলি তৈরি করা যায়, যেগুলি একটি সহজ টার্মে "অবজেক্ট" হিসেবে পরিচিত। বিভিন্ন সময় এসব ডেটা সংরক্ষনের পাশাপশি সংশোধন, পরিবর্তন বা পরিবর্ধনের প্রয়োজন হয়। এ প্রক্রিয়া সম্পন্ন করার জন্য দুটি পদ্ধতি রয়েছে। যেমন:-   
 
 1. **মিউটেশন (Mutation)**
 2. **ইমিউটেশন (Immutation)**

## Mutation এবং Immutation-এর পার্থক্য কি?

1. **মিউটেশন (Mutation):**
    - **ডেটা পরিবর্তন:** মিউটেশন হলো এমন একটি প্রক্রিয়া যার ফলে ডেটা স্ট্রাকচারের মৌলিক অবস্থার পরিবর্তন হয়।
    - **এক্সিটিং ডেটায় পরিবর্তন:** মিউটেবল প্রোগ্রামিং এ ডেটা তৈরি হওয়ার পরে সেই ডেটা পরিবর্তনের ফলে  এক্সিটিং ডেটায় পরিবর্তন হয়। অর্থাৎ, পূর্বের ডেটা ওভার-রাইট বা মডিফাই হয়ে যায়।
    - **রেফারেন্স পরিবর্তন:** মিউটেশনের সময়ে, অবজেক্ট বা ডেটা স্ট্রাকচার এর মৌলিক রেফারেন্স পরিবর্তন হতে পারে ।
    - **ডেটা পরিবর্তন এবং স্টেট  পরিবর্তন:** মিউটেশনের ফলে একটি স্টেটফুল প্রোগ্রামিং প্যারাডাইম অনুসরণ করে, যেখানে ডেটা পরিবর্তন হওয়ার সাথে সাথে স্টেট ও পরিবর্তন হয়।
2. **ইমিউটেশন:**
    - **ডেটা পরিবর্তন:** ইমিউটেবলিটি বা ইমিউটেবল প্রোগ্রামিং হলো এমন একটি প্রোগ্রামিং প্যারাডাইম যেখানে ডেটা পরিবর্তন হতে পারে না, বরং নতুন ডেটা তৈরি করে বা পূর্বের ডেটা কপি করে সেখানে নতুন ডেটা সংযোজনের পর সেটি প্রতিস্থাপন করতে হয়।
    - **এক্সিটিং ডেটায় পরিবর্তন নয়:** ইমিউটেবল প্রোগ্রামিং এ ডেটা তৈরি হওয়ার পরে সেই ডেটা পরিবর্তনের ফলে  এক্সিটিং ডেটায় কোনো পরিবর্তন হয় না। অর্থাৎ, পূর্বের ডেটা ওভার-রাইট বা মডিফাই করা হয় না।
    - **রেফারেন্স পরিবর্তন :** ইমিউটেবল ডেটা স্ট্রাকচার তৈরি করলে তার রেফারেন্স পরিবর্তন হয় না।
    - **ডেটা তৈরি এবং স্টেট সংরক্ষণ:** ইমিউটেবল প্রোগ্রামিং-এ ডেটা এবং স্টেট সংরক্ষিত থাকে এবং এটি পরিবর্তন করা যায় না। এটি একটি ফাংশনাল প্রোগ্রামিং প্যারাডাইমের উপাদান।

**উপকারিতা:**

- **মিউটেশন:**
    - সময়ের সাথে ডেটা আপডেটেড থাকতে পারে।
    - প্রোগ্রাম চালাতে হলে কম্পিউটেশনাল প্রোগ্রামিং থেকে অনেক বেশি পরিচিত এবং সুবিধাজনক।
- **ইমিউটেশন:**
    - এক্সিটিং ডেটা অক্ষত বা স্থায়ী থাকতে পারে, যা ডেটা ওভার-রাইট বা মডিফাই হয়ে যাওয়ার সম্ভাবনা কমায়।
    - টেস্টিংয়ে সহায়ক।
    - বড় এবং জটিল প্রোগ্রামগুলির ম্যানেজমেন্ট করা সহজ হয়।

## রিয়্যাক্ট লাইব্রেরী কেনো State মিউটেশনকে “না” বলে?

 রিয়্যাক্ট ডিক্ল্যারেটিভ এবং ফাংশনাল কনসেপ্ট অনুসরণ করে, যা লজিক বা প্রোগ্রাম বিবেচনা করে কিংবা এটি কিভাবে কাজ করছে তা নির্দিষ্ট করে। প্রোগ্রামিং এবং কম্পিউটার সাইন্সের কনসেপ্টে ডেটা মিউটেশান একটি মৌলিক ধারনা হলেও ফেসবুক এর জনপ্রিয় লাইব্রেরী রিয়্যাক্ট তাদের লাইব্রেরীতে ডেটা মিউটেশান করতে বা State Mutating করতে  নিরুৎসাহিত করে। আপনি যদি `console.log` ব্যবহার করেন এবং State mutation না করেন বা  Immutation করেন তবে আপনার Initial Render-এ `console.log`  এর আউটপুট এবং Re-Render-এ `console.log` এর আউটপুট দুটোই ভিন্ন ভিন্ন হবে। কিন্তু আপনি যদি State mutation  করেন তাহলে Initial Render এবং Re-Render দুটো `console.log` এর আউটপুট একই দেখাবে। চলুন এবার মিউটেশান এবং ইমিউটেশান এর দুটো উদাহরণ দেখা যাক।
</main> 

**ইমিউটেশন (Immutation) উদাহরণ:**

```jsx
import { useState } from "react";
export default function App() {
  const [person, setPerson] = useState({ name: "John", age: 25 });

  // (কনসোল - ১) ইনসিয়াল রেন্ডার / ফাস্ট স্ন্যাপশট
  console.log("ইনিসিয়াল রেন্ডারে বয়স:", person.age);

  const handleAgeChange = () => {
    const newPerson = { ...person, age: 26 };
    setPerson(newPerson);

    // (কনসোল - ২) রি-রেন্ডার / আপডেটেড স্ন্যাপশট
    console.log(
      "(Increase Age) বাটনে ক্লিক করে রি-রেন্ডার হওয়ার পর age:",
      newPerson.age
    );
  };

  return (
    <div>
      <p>Name: {person.name}</p>
      <p>Age: {person.age}</p>
      <button onClick={handleAgeChange}>Increase Age</button>
    </div>
  );
}
```

***মন্তব্য:***

`Increase Age` বাটনে ক্লিক করার পর প্রথমে `handleAgeChange` ফাংশনে `newPerson` অবজেক্টের `age` প্রোপাটির ভ্যালু আপডেট হবে
(অর্থাৎ, পূর্বের ভ্যালুর সাথে ১ যোগ হবে) এই আপডেটেড ভ্যালু  কনসোল - ২ প্রিন্ট করবে
সাথে সাথে এই আপডেটেড `newPerson`  অবজেক্টটিকে `setPerson` ফাংশন ক্যারি করে নিয়ে যাবে
এরপর পূর্বের বা ব্যাকডেটেড যে person  অবজেক্ট ছিলো সেটাকে `newPerson` অবজেক্ট দিয়ে Replace করে দিবে
তখনই কম্পোনেন্ট Re-Render ট্রিগার করবে এবং UI আপডেটেড ভ্যালু প্রিন্ট করবে।

**মিউটেশন (Mutation) উদাহরণ:**

```jsx
import React, { useState } from "react";

function App() {
  const [person, setPerson] = useState({ name: "John", age: 25 });

  // (কনসোল - ১) ইনিসিয়াল রেন্ডার / ফাস্ট স্ন্যাপশট
  console.log("Initial age:", person.age);
  const handleAgeChange = () => {
    person.age = 26;
    setPerson(person);

    // (কনসোল - ২) রি-রেন্ডার / আপডেটেড স্ন্যাপশট
    console.log(
      "(Increase Age) বাটনে ক্লিক করার পর age:",
      person.age
    );
  };

  return (
    <div>
      <p>Name: {person.name}</p>
      <p>Age: {person.age}</p>
      <button onClick={handleAgeChange}>Increase Age</button>
    </div>
  );
}

export default App;
```

***মন্তব্য:***

<aside> `Increase Age` বাটনে ক্লিক করার পর প্রথমে `handleAgeChange` ফাংশনে `person.age = 26` হবে ফলে `age` প্রোপাটির পূর্বের ভ্যালু আপডেট না হয়ে মিউটেট হয়ে যাবে  । বিষয়টা অনেকটা এমন যে, আপনি প্রথমে খাতায় `age = 25` লিখলেন। কিন্তু পরোক্ষণে আবার কিছু একটা ভেবে age = ~~25~~ কেটে  `26` লিখলেন। **রিয়্যাক্ট বলবে,** আমি এমন কাঁটাছেড়া লেখা পছন্দ করি না আপনি তার চেয়ে ভালো আমাকে নতুন একটা লাইনে(Index-এ) `age = 26` লিখে দিন আমি সেটাই `age` এর ভ্যালু হিসেবে রিপ্লেস করে কম্পোনেন্ট রি-রেন্ডার করে দিবো। আমি **Pure function rules** - এ বিশ্বাসী সেইম ইনপুটের জন্য সেইম আউটপুট `return` করব। আপনি যাত্রা পথে এম্বুলেন্সে রেখেই রোগী সার্জারী`(State mutate)` করতে বলবেন এরপর রোগী মারা গেলে `Bug ক্রিয়েট হলে`  সব দোষ আমাকেই দিবেন এমন তো হতে পারে না। বরং আমাকে এমন ঝুঁকিপূর্ণ কাজ করার নির্দেষ দেওয়া থেকে বিরত থাকুন নিজেকেও `Bug থেকে` নিরাপদে রাখুন। অর্থাৎ, এধরনের বাগ ক্রিয়েট করা থেকে বিরত থাকতে হলে State mutation কে না বলতে হবে। রোগীর সার্জারী কেবল হসপিটালেই হোক, এম্বুলেন্সে নয়। `Mutation কেবল “Local mutation”-এ হোক, "Golobal mutation"-এ নয়।`

</aside>


## কেনো State mutated হলে Component Re-Render হয় না?

> রিয়্যাক্টে একটি কম্পোনেন্ট রি-রেন্ডার  তখনই হয় যখন স্টেট বা প্রপার্টি আপডেট হয়। অর্থাৎ, Initial Render বা ফাস্ট স্ন্যাপশট এর সাথে Re-Render বা আপডেটেড স্ন্যাপশট-এর মধ্যে তুলনা করে কোন পরিবর্তন সনাক্ত করা গেলে তখন State Re-Render হয়। কিন্তু, স্টেট মিউটেশন (State Mutation) করলে কম্পোনেন্ট রি-রেন্ডার হয় না এর কিছু কারণ রয়েছে।
> 
> 
> রিয়্যাক্ট-এ স্টেট আপডেট করলে কম্পোনেন্ট রি-রেন্ডার হবে যদি নিম্নলিখিত কোনো একটি কন্ডিশন সত্য হয়:
> 
> 1. **Immutability :** রিয়্যাক্টে স্টেট আপডেট করতে হলে, স্টেট অবজেক্ট অথবা অ্যারে ইমিউটেটেড (অপরিবর্তনযোগ্য) হতে হবে। ইমিউটেবল অবজেক্ট বা অ্যারে তৈরি করার উপায় হলো নতুন অবজেক্ট বা অ্যারে তৈরি করা অথবা মৌলিক অবজেক্ট বা অ্যারে কপি করে সেটার মাধ্যমে পরিবর্তন করা। এটির মাধ্যমে রিয়্যাক্ট অবজেক্ট অথবা অ্যারের পরিবর্তন ডিটেক্ট করতে পারে এবং কম্পোনেন্ট রি-রেন্ডার করতে পারে।
> 2. **অবজেক্ট এবং অ্যারে রেফারেন্স চেক:** রিয়্যাক্ট কম্পোনেন্ট রেন্ডার করার সময়, স্টেটের অবজেক্ট বা অ্যারে রেফারেন্স চেক করে কোন রেফারেন্স পরিবর্তন হয়েছে কিনা। যদি এক্সিটিং অবজেক্ট অথবা অ্যারের রেফারেন্স একই থাকে তবে কম্পোনেন্ট রি-রেন্ডার হয় না, কারণ রিয়্যাক্ট কম্পোনেন্ট রি-রেন্ডার করার জন্য কোনো নতুন রেফারেন্স খুঁজে না পেলে রি-রেন্ডার ট্রিগার করবে না।


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5zbwubjpkmlkzf9ike41.png)