কম্পোনেন্টগুলোর মধ্যে স্টেট শেয়ার করা
🔼 State উপরে তোলা (Lifting State Up)
Intro:
অনেক সময় এমন হয়, দুইটা কম্পোনেন্ট আছে যাদের স্টেট একসাথে পরিবর্তন হওয়া দরকার।
এই কাজটা করার জন্য — তাদের ভিতরের state মুছে ফেলো, এবং সবচেয়ে কাছের common parent কম্পোনেন্টে state রাখো। তারপর সেই state এবং সেটার setter function প্রপস হিসেবে নিচের কম্পোনেন্টগুলোর মধ্যে শেয়ার করে দাও।
এটাকেই বলে lifting state up, এবং এটা React এ সবচেয়ে বেশি ইউজ হওয়া কৌশলগুলোর একটা।
🎯 তুমি যা শিখবে:
- কম্পোনেন্টগুলোর মধ্যে state শেয়ার করার নিয়ম
- Controlled vs Uncontrolled কম্পোনেন্ট কী
🧪 উদাহরণ দিয়ে বোঝা যাক – Lifting State Up
এই উদাহরণে একটা parent কম্পোনেন্ট Accordion
আছে, যেটা দুইটা Panel
কম্পোনেন্ট রেন্ডার করে:
Accordion
├── Panel
└── Panel
প্রতিটা Panel
কম্পোনেন্টের ভিতরে একটা isActive
নামে boolean
টাইপের state আছে, যেটা ঠিক করে প্যানেলের content দেখাবে কি না।
প্রতিটা Panel-এর "Show" বাটনে ক্লিক করলে তার content দেখা যাবে। নিচে কোডটা দেখো:
🧾 Accordion কম্পোনেন্টের কোড
import { useState } from "react";
function Panel({ title, children }) {
const [isActive, setIsActive] = useState(false);
return (
<section className="panel">
<h3>{title}</h3>
{isActive ? (
<p>{children}</p>
) : (
<button onClick={() => setIsActive(true)}>Show</button>
)}
</section>
);
}
export default function Accordion() {
return (
<>
<h2>Almaty, Kazakhstan</h2>
<Panel title="About">
With a population of about 2 million, Almaty is Kazakhstan's largest
city. From 1929 to 1997, it was its capital city.
</Panel>
<Panel title="Etymology">
The name comes from <span lang="kk-KZ">алма</span>, the Kazakh word for
"apple" and is often translated as "full of apples". In fact, the region
surrounding Almaty is thought to be the ancestral home of the apple, and
the wild
<i lang="la">Malus sieversii</i> is considered a likely candidate for the
ancestor of the modern domestic apple.
</Panel>
</>
);
}
🎨 CSS:
h3,
p {
margin: 5px 0px;
}
.panel {
padding: 10px;
border: 1px solid #aaa;
}
🔍 এখন লক্ষ্য করো:
প্রতিটা Panel আলাদা আলাদা ভাবে state ম্যানেজ করে। একটা Panel-এর "Show" বাটনে ক্লিক করলে কেবল সেই Panel-এর content দেখা যায় — অন্যটাতে কোনো প্রভাব পড়ে না।
এখন যদি তোমার দরকার হয় যে — একটা Panel খুললে আরেকটা অটোমেটিক বন্ধ হয়ে যাবে, তখন তোমাকে state দুইটা Panel থেকে তুলে Accordion
কম্পোনেন্টে নিতে হবে। এটাকেই বলে lifting state up।
🎯 মূল কথা কী?
প্রথমে দুইটা Panel
কম্পোনেন্ট আলাদা আলাদা isActive
state দিয়ে কাজ করত, তাই একটা প্যানেল খোলা হলে অন্যটা বন্ধ হত না। এখন আমরা এমন একটা অবস্থা বানাতে চাই, যেখানে একটা Panel খোলা হলে অন্যটা স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে।
এইটার জন্যই দরকার "lifting state up", অর্থাৎ state দুইটা child থেকে সরিয়ে parent component Accordion
-এ তোলা। এর মাধ্যমে parent পুরোটা control করতে পারবে।
🔄 পরিবর্তন ধাপে ধাপে
✅ Step 1: Child থেকে state সরাও
আগে Panel
এর ভিতরে ছিলঃ
const [isActive, setIsActive] = useState(false);
এখন এটা মুছে ফেলো। কারণ এখন Panel
নিজের state নিজে ম্যানেজ করবে না।
তারপর, isActive
কে প্রপস আকারে গ্রহণ করো:
function Panel({ title, children, isActive }) {
এটা মানে Panel
এখন শুধু উপরের থেকে (parent থেকে) বলা অনুযায়ী দেখাবে বা লুকাবে।
✅ Step 2: Parent থেকে manually ডেটা দাও
এখন parent component Accordion
থেকে নিচের দুইটা Panel
-এ isActive={true}
বা false
হ্যান্ডল করে দিয়ে চেক করো। যেমনঃ
<Panel title="About" isActive={true}>...</Panel>
<Panel title="Etymology" isActive={false}>...</Panel>
তবে এটা এখনো হার্ডকোড করা—মানে আমরা ম্যানুয়ালি দিচ্ছি কোনটা true, কোনটা false।
✅ Step 3: এখন আসল কাজ—parent এ state নিয়ে আসো
এখন parent component Accordion
-এ একটা state রাখো, যেটা বলে কোন Panel active:
const [activeIndex, setActiveIndex] = useState(0);
মানে, যদি activeIndex === 0
, তাহলে প্রথম প্যানেল active। যদি 1
হয়, তাহলে দ্বিতীয়টা।
এখন আমরা Panel
এ isActive
হিসেব করব activeIndex
এর ভিত্তিতে:
<Panel
title="About"
isActive={activeIndex === 0}
onShow={() => setActiveIndex(0)}
>
<Panel
title="Etymology"
isActive={activeIndex === 1}
onShow={() => setActiveIndex(1)}
>
এখানে onShow
হল একটা ফাংশন যা child থেকে parent-এর setActiveIndex()
কল করবে।
এখন Panel
এর ভিতরে button
ক্লিক করলে এই onShow
চালাবে:
<button onClick={onShow}>Show</button>
🔁 এখন কি হলো?
- এখন
Accordion
parent জানে কোনটা active (index দিয়ে track করে)। - এক প্যানেল active হলে অন্যটা inactive হয়।
- দুইটা
Panel
এখন completely controlled by parent. - সব কিছু এক জায়গা থেকে ম্যানেজ হয়—এটাই lifting state up-এর মূল শক্তি।
💡 Real Life Analogy
ভাবো তুমি দুইটা light switch বানাইছো। আগে দুইটা নিজের মতো করে চালু/বন্ধ হতো। এখন তুমি এমনভাবে করলা যে একটা চালু হলে, আরেকটা অটো বন্ধ হয়ে যাবে। তুমি দুইটার নিয়ন্ত্রণ একটা remote (parent component) দিয়ে করতেছো।
Great! Here's a clear and simple summary of the 3rd Part in Bangla with examples to help you understand better:
✅ Controlled এবং Uncontrolled Components কী?
🔹 Uncontrolled Component:
যখন একটি কম্পোনেন্ট তার নিজের ভিতরে state রেখে নিজে নিজে নিয়ন্ত্রণ করে, তখন সেটি uncontrolled component।
উদাহরণ:
function Panel() {
const [isActive, setIsActive] = useState(false);
// নিজেই isActive state নিয়ন্ত্রণ করছে
}
এখানে Panel
কম্পোনেন্ট নিজের state নিজেই চালাচ্ছে, parent কিছু জানে না—তাই এটি uncontrolled।
🔹 Controlled Component:
যখন parent component props
দিয়ে কোনো কম্পোনেন্টের state নিয়ন্ত্রণ করে, তখন সেটি controlled component।
উদাহরণ:
function Accordion() {
const [activeIndex, setActiveIndex] = useState(0);
return <Panel isActive={activeIndex === 0} />;
}
function Panel({ isActive }) {
// parent এর props অনুযায়ী কাজ করছে
}
এখানে Accordion
parent isActive
props পাঠিয়ে Panel
কম্পোনেন্ট নিয়ন্ত্রণ করছে—তাই এটি controlled।
🔁 কোনটা বেছে নেবেন?
Controlled | Uncontrolled |
---|---|
Parent সব কিছু নিয়ন্ত্রণ করে | Component নিজে নিজে কাজ করে |
Flexible, coordination সহজ | ব্যবহার করা সহজ, configuration কম |
Props দিয়ে চালানো হয় | State দিয়ে চালানো হয় |
➡️ যখন দুইটা বা তার বেশি কম্পোনেন্টকে co-ordinate করতে হবে (যেমন একটাকে active করলে অন্যটা বন্ধ হবে), তখন controlled approach ব্যবহার করা ভালো।
👉 Uncontrolled কম্পোনেন্টস ব্যবহার করা সহজ, কারণ কম কনফিগারেশন লাগে।
👉 কিন্তু Controlled কম্পোনেন্টস বেশি ফ্লেক্সিবল—parent পুরোপুরি কাস্টম কন্ট্রোল রাখতে পারে, যদিও কিছুটা কোড বেশি লিখতে হয়।
বাস্তবে, অনেক কম্পোনেন্টেই props আর state মিশিয়ে কাজ করা হয়—পুরোপুরি controlled বা uncontrolled না হলেও, এই দুই টার্ম আমাদেরকে component গুলো বুঝতে সাহায্য করে।
তোমার কম্পোনেন্ট লেখার সময় ভাবো, কোন তথ্যগুলো parent থেকে নিয়ন্ত্রণ করবে (controlled), আর কোনগুলো কম্পোনেন্টের ভিতরে থাকবে (uncontrolled)। দরকার হলে পরে refactor করে পাল্টানো যায়।
প্রতিটি state-এর জন্য একটি নির্দিষ্ট মালিক (Single Source of Truth)
React অ্যাপে অনেক কম্পোনেন্টের নিজস্ব state থাকে। কিছু state নিচের দিকের কম্পোনেন্টে থাকে (যেমন ইনপুট), আবার কিছু উপরের দিকে থাকে (যেমন পুরো অ্যাপের রাউট)। অনেক সময় client-side রাউটিংও React state ব্যবহার করে করে তৈরি হয় এবং সেই রাউট parent থেকে props দিয়ে নিচে পাঠানো হয়।
👉 প্রতিটি আলাদা state-এর জন্য, এমন একটি কম্পোনেন্ট ঠিক করো যেটা ঐ তথ্যের মালিক হবে। এটাকেই আমরা বলি single source of truth।
এর মানে এই না যে সব স্টেট উপরের এক জায়গায় রাখতে হবে, বরং প্রতিটি স্টেট যেন একটাই কম্পোনেন্টে থাকে, যাতে ডেটা কনসিস্টেন্ট থাকে।
যদি কোনো স্টেট দুইটা কম্পোনেন্টে প্রয়োজন হয়, তাহলে সেটাকে উপরের কমন parent-এ নিয়ে যাও (lift it up), আর props দিয়ে নিচে পাঠাও।
React অ্যাপ বানাতে গেলে, এই state কোথায় থাকবে সেটা বারবার চিন্তা করে বদলাতে হতে পারে—এটা স্বাভাবিক!
👉 এর বেশি ভালোভাবে অনুশীলনের জন্য, "Thinking in React" (opens in a new tab) পড়তে পারো।
যেমন:
// Accordion holds the main truth of which panel is active
const [activeIndex, setActiveIndex] = useState(0);
এই concept বলে:
- ডুপ্লিকেট state তৈরি করবেন না
- যেসব কম্পোনেন্টে সেই state দরকার, তাদের parent থেকে props দিয়ে পাঠিয়ে দিন
- যেটা state পরিবর্তন করতে চায়, তাকে একটি event handler দিয়ে দিন
এই অংশটা আমি তোমার জন্য সহজভাবে React ডেভেলপার হিসেবে বাংলায় অনুবাদ করে দিলাম, যাতে তুমি বুঝতে পারো ঠিক কী বলা হচ্ছে, আর কিভাবে বাস্তব জীবনের React প্রজেক্টে এই জিনিসগুলো কাজে লাগবে:
সারাংশ (Recap):
- দুইটা কম্পোনেন্ট একসাথে কাজ করাতে চাইলে, তাদের state উপরের কমন parent এ রাখো।
- তারপর সেই ডেটা নিচের দিকে props দিয়ে পাঠাও।
- event handlers-ও নিচে পাঠাও যেন child কম্পোনেন্ট parent-এর state পরিবর্তন করতে পারে।
- কম্পোনেন্টগুলোকে controlled (props দিয়ে কন্ট্রোল করা) আর uncontrolled (নিজের স্টেট দিয়ে চালানো) হিসেবে ভাবলে ডিজাইন ক্লিয়ার হয়।