আগের পর্বে আমরা Conditional Rendering শিখেছিলাম। এই পর্বে আমরা দেখব List Rendering — কীভাবে একটা অ্যারে থেকে একগুচ্ছ UI এলিমেন্ট তৈরি করা যায়, আর key prop কেন এত গুরুত্বপূর্ণ, যেটা আমরা আগের পর্বগুলোতে সংক্ষেপে ব্যবহার করেছিলাম কিন্তু ব্যাখ্যা করিনি।
map() দিয়ে তালিকা বানানো
Advanced JS-এ শেখা .map() মেথড React-এ তালিকা বানানোর মূল হাতিয়ার — একটা অ্যারের প্রতিটা আইটেম থেকে একটা JSX এলিমেন্ট তৈরি করা হয়।
function FruitList() {
const fruits = ["আম", "কাঁঠাল", "লিচু"];
return (
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
);
}
এখানে fruits.map() তিনটা <li> এলিমেন্টের একটা অ্যারে রিটার্ন করছে, আর React সেগুলোকে { }-এর ভেতরে দেখে সরাসরি স্ক্রিনে রেন্ডার করছে।
অবজেক্টের অ্যারে থেকে তালিকা
বাস্তব প্রজেক্টে সাধারণত সাধারণ স্ট্রিং না, অবজেক্টের অ্যারে থাকে — Props পর্বে দেখা books অ্যারের কথা মনে করো।
function BookList() {
const books = [
{ id: 1, title: "সোনার তরী", author: "রবীন্দ্রনাথ ঠাকুর" },
{ id: 2, title: "পথের পাঁচালী", author: "বিভূতিভূষণ" },
{ id: 3, title: "চোখের বালি", author: "রবীন্দ্রনাথ ঠাকুর" }
];
return (
<div>
{books.map((book) => (
<div key={book.id}>
<h3>{book.title}</h3>
<p>{book.author}</p>
</div>
))}
</div>
);
}
key prop কেন জরুরি?
প্রতিটা লিস্ট আইটেমে key দেওয়া বাধ্যতামূলক (না দিলে console-এ warning আসবে)। key React-কে সাহায্য করে প্রতিটা আইটেমকে "চিনতে" — তালিকায় কিছু যোগ, বাদ, বা পুনর্বিন্যাস হলে React বুঝতে পারে ঠিক কোন আইটেমটা পাল্টেছে, কোনটা একই আছে।
key ছাড়া React শুধু position (অবস্থান) দিয়ে তুলনা করে, যেটা ভুল আপডেটের দিকে নিয়ে যেতে পারে — বিশেষ করে যখন তালিকার মাঝখান থেকে কিছু বাদ দেওয়া হয় বা যোগ করা হয়।
সঠিক key কী হওয়া উচিত?
| key হিসেবে | ভালো নাকি খারাপ |
|---|---|
ডেটাবেজ থেকে আসা ইউনিক id |
✅ সবচেয়ে ভালো |
| ইউনিক স্ট্রিং (যেমন ইমেইল, স্লাগ) | ✅ ভালো, যদি সত্যিই ইউনিক হয় |
map()-এর index |
⚠️ শুধু তখনই ঠিক আছে যদি তালিকা কখনো পুনর্বিন্যাস/এডিট না হয় |
Math.random() |
❌ কখনোই না — প্রতিবার নতুন মান, key-এর পুরো উদ্দেশ্যই নষ্ট |
Index কে key হিসেবে ব্যবহারের সমস্যা — বাস্তব উদাহরণ
চলো দেখি কেন index দিয়ে সমস্যা হতে পারে — একটা তালিকা থেকে মাঝখানের আইটেম মুছে ফেললে কী ঘটে।
// ধরো তালিকা: ["আম", "কাঁঠাল", "লিচু"] // index দিয়ে key: 0, 1, 2 // "কাঁঠাল" মুছে ফেলার পর: ["আম", "লিচু"] // এখন index দিয়ে key: 0, 1 // React ভাবে: index=1 এখনো আছে, তাই "লিচু"-কে "কাঁঠাল"-এর জায়গায় re-render করবে // index=2 চলে গেছে, তাই শেষের এলিমেন্ট DOM থেকে মুছে দেবে // এতে যদি প্রতিটা আইটেমে input বা কোনো লোকাল স্টেট থাকে (যেমন checkbox checked অবস্থা), // সেই স্টেট ভুল আইটেমে থেকে যেতে পারে — কারণ React ভুলভাবে ধরে নেয় একই "জিনিস" আছে
ইউনিক id ব্যবহার করলে এই সমস্যা হয় না — React ঠিকভাবে বুঝতে পারে কোন আইটেম আসলেই বাদ গেছে, কোনটা একই আছে।
লাইভ ডেমো — তালিকায় যোগ ও বাদ দেওয়া
নিচে useState (পর্ব ৫), Spread (Advanced JS পর্ব ৫), আর map() মিলিয়ে একটা ডাইনামিক তালিকা — নতুন আইটেম যোগ করো, মুছে ফেলো।
map()-এর ভেতরে কন্ডিশনাল লজিক মেলানো
আগের পর্বের Conditional Rendering আর এই পর্বের List Rendering প্রায়ই একসাথে ব্যবহার হয় — যেমন প্রতিটা আইটেমে ভিন্ন স্টাইল দেওয়া।
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li
key={todo.id}
style={{ textDecoration: todo.done ? "line-through" : "none" }}
>
{todo.done && "✅ "}
{todo.text}
</li>
))}
</ul>
);
}
খালি তালিকা হ্যান্ডেল করা
Conditional Rendering (আগের পর্ব) দিয়ে খালি তালিকার জন্য একটা বন্ধুত্বপূর্ণ মেসেজ দেখানো ভালো অভ্যাস — খালি স্ক্রিন ব্যবহারকারীকে বিভ্রান্ত করতে পারে।
function BookList({ books }) {
if (books.length === 0) {
return <p>এখনো কোনো বই যোগ করা হয়নি</p>;
}
return (
<ul>
{books.map((book) => <li key={book.id}>{book.title}</li>)}
</ul>
);
}
একটা সম্পূর্ণ উদাহরণ — ফিল্টার করা তালিকা
Advanced JS-এ শেখা .filter() আর .map() একসাথে চেইন করে সার্চ/ফিল্টার ফিচার বানানো যায়।
function SearchableBookList() {
const [query, setQuery] = React.useState("");
const books = [
{ id: 1, title: "সোনার তরী" },
{ id: 2, title: "পথের পাঁচালী" },
{ id: 3, title: "চোখের বালি" }
];
const filteredBooks = books.filter((book) =>
book.title.includes(query)
);
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="বই খুঁজুন"
/>
{filteredBooks.length === 0 ? (
<p>কোনো বই পাওয়া যায়নি</p>
) : (
<ul>
{filteredBooks.map((book) => <li key={book.id}>{book.title}</li>)}
</ul>
)}
</div>
);
}
এখানে প্রতিবার টাইপ করলে filter() নতুন করে চলছে, আর ফলাফল অনুযায়ী map() তালিকা আপডেট করছে — এটাই পর্ব ১৮-এর মিনি প্রজেক্টে (Product List with Search/Filter) আরও বিস্তারিত দেখব।
নিজে চেষ্টা করো
Exercise:
- উপরের
FruitListডেমো নিজে বানাও, নিজের পছন্দের ৫টা জিনিস দিয়ে শুরু করো। - একটা তালিকায় ইচ্ছাকৃতভাবে
key={index}ব্যবহার করো, তারপরidদিয়ে পাল্টাও — console-এ কোনো warning পার্থক্য দেখো কিনা। - উপরের
SearchableBookListনিজে বানাও, নিজের পছন্দের বইয়ের তালিকা দিয়ে। - একটা তালিকা বানাও যেখানে খালি হলে "কিছু নেই" মেসেজ দেখাবে, আগের পর্বের Conditional Rendering কৌশল ব্যবহার করে।
পরের পর্বে যা থাকছে
এতদিন যা শিখেছি তা দিয়েই "State ও Interactivity" অংশ শেষ হলো। পরের পর্ব থেকে শুরু হবে "ফর্ম ও ডেটা হ্যান্ডলিং" — প্রথম টপিক Controlled Component, যেখানে আমরা শিখব কীভাবে ফর্ম ইনপুট সম্পূর্ণভাবে React দিয়ে নিয়ন্ত্রণ করা যায়।