কম্পোনেন্টে Props পাস করা
React কম্পোনেন্টগুলো একে অপরের সাথে কথা বলার জন্য props
ব্যবহার করে। প্রত্যেক প্যারেন্ট কম্পোনেন্ট তার চাইল্ড কম্পোনেন্টকে props
দিয়ে কিছু তথ্য পাঠাতে পারে। Props অনেকটা HTML অ্যাট্রিবিউটের মতো, কিন্তু এর মাধ্যমে তুমি জাভাস্ক্রিপ্টের যেকোনো ভ্যালু—যেমন অবজেক্ট, অ্যারে, এমনকি ফাংশনও—পাস করতে পারো।
কি কি শিখবে এই পাঠে
- কীভাবে একটি কম্পোনেন্টে
props
পাস করতে হয়। - কীভাবে একটি কম্পোনেন্ট থেকে
props
পড়তে হয়। - কীভাবে
props
-এর জন্য ডিফল্ট ভ্যালু সেট করতে হয়। - কীভাবে একটি কম্পোনেন্টে JSX পাস করতে হয়।
- সময়ের সাথে সাথে
props
কীভাবে পরিবর্তিত হয়।
তোমার পরিচিত props
Props হলো সেই তথ্য যা তুমি একটি JSX ট্যাগের মধ্যে পাস করো। উদাহরণস্বরূপ, className
, src
, alt
, width
, এবং height
হলো কিছু props যা আমরা প্রায়ই <img>
ট্যাগে ব্যবহার করি:
function Avatar() {
return (
<img
className="avatar"
src="https://i.imgur.com/1bX5QH6.jpg"
alt="Lin Lanying"
width={100}
height={100}
/>
);
}
<img>
-এর মতো বিল্ট-ইন ট্যাগের props গুলো আগে থেকেই নির্ধারিত থাকে। কিন্তু তুমি তোমার নিজের বানানো কম্পোনেন্টে (যেমন: <Avatar />
) যেকোনো কাস্টম props পাস করে তাকে আরও শক্তিশালী করে তুলতে পারো। চলো দেখি কীভাবে!
একটি কম্পোনেন্টে Props পাস করা
এই কাজটি তুমি দুটি সহজ ধাপে করতে পারো:
ধাপ ১: চাইল্ড কম্পোনেন্টে props পাস করা
প্রথমে, প্যারেন্ট কম্পোনেন্ট থেকে চাইল্ড কম্পোনেন্টে কিছু props পাস করো। যেমন, <Avatar />
কম্পোনেন্টে আমরা person
(একটি অবজেক্ট) এবং size
(একটি সংখ্যা) নামে দুটি props পাস করছি:
export default function Profile() {
return (
<Avatar person={{ name: "Lin Lanying", imageId: "1bX5QH6" }} size={100} />
);
}
ধাপ ২: চাইল্ড কম্পোনেন্টে props পড়া
এখন, Avatar
কম্পোনেন্টের ভেতরে এই props
গুলোকে পড়তে হবে। ফাংশন ডেফিনিশনের মধ্যে ({
})
ব্র্যাকেটের ভেতরে props-গুলোর নাম কমা দিয়ে আলাদা করে লিখে দাও। এই সিনট্যাক্সকে "ডিস্ট্রাকচারিং" (destructuring) বলে।
function Avatar({ person, size }) {
// person এবং size এখন এখানে ভ্যারিয়েবলের মতো ব্যবহার করা যাবে
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
এখন তুমি Avatar
কম্পোনেন্টটিকে ভিন্ন ভিন্ন props দিয়ে অনেকভাবে ব্যবহার করতে পারো। নিচের উদাহরণে মানগুলো পরিবর্তন করে দেখো!
import { getImageUrl } from "./utils.js";
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
export default function Profile() {
return (
<div>
<Avatar
size={100}
person={{
name: "Katsuko Saruhashi",
imageId: "YfeOqp2",
}}
/>
<Avatar
size={80}
person={{
name: "Aklilu Lemma",
imageId: "OKS67lh",
}}
/>
<Avatar
size={50}
person={{
name: "Lin Lanying",
imageId: "1bX5QH6",
}}
/>
</div>
);
}
export function getImageUrl(person, size = "s") {
return "https://i.imgur.com/" + person.imageId + size + ".jpg";
}
body {
min-height: 120px;
}
.avatar {
margin: 10px;
border-radius: 50%;
}
Props কে তুমি একটি যন্ত্রের "নব" (knob)-এর মতো ভাবতে পারো, যা ঘুরিয়ে তুমি কম্পোনেন্টের আচরণ পরিবর্তন করতে পারো।
Props-এর জন্য ডিফল্ট মান নির্দিষ্ট করা
যদি তুমি চাও যে কোনো props পাস করা না হলে একটি ডিফল্ট মান ব্যবহৃত হোক, তবে ডিস্ট্রাকচারিং করার সময় =
চিহ্ন দিয়ে সেই মানটি সেট করে দিতে পারো।
function Avatar({ person, size = 100 }) {
// ...
}
এখন যদি কেউ <Avatar person={...} />
রেন্ডার করে এবং size
prop না দেয়, তাহলে size
-এর মান স্বয়ংক্রিয়ভাবে 100
হয়ে যাবে। ডিফল্ট মান কেবল তখনই কাজ করে যখন prop পাস করা হয় না অথবা undefined
পাস করা হয়। null
বা 0
পাস করলে ডিফল্ট মান কাজ করবে না।
JSX স্প্রেড সিনট্যাক্স দিয়ে Props ফরওয়ার্ড করা
মাঝে মাঝে একটি প্যারেন্ট কম্পোনেন্ট তার সব props চাইল্ড কম্পোনেন্টে পাস করে দেয়। তখন প্রত্যেকটি prop আলাদাভাবে না লিখে তুমি স্প্রেড সিনট্যাক্স ...
ব্যবহার করতে পারো।
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
এটি Profile
-এর সব props-কে Avatar
-এর কাছে পাঠিয়ে দেবে। তবে এই সিনট্যাক্স খুব ভেবেচিন্তে ব্যবহার করা উচিত, কারণ এটি কোডকে কিছুটা অস্পষ্ট করে তুলতে পারে।
JSX-কে children হিসেবে পাস করা
HTML-এর মতো তুমি তোমার নিজের কম্পোনেন্টও নেস্ট করতে পারো:
<Card>
<Avatar />
</Card>
যখন তুমি এভাবে কোনো কন্টেন্ট নেস্ট করো, তখন প্যারেন্ট কম্পোনেন্ট (Card
) সেই কন্টেন্টটিকে children
নামে একটি বিশেষ prop-এ পায়। তুমি children
prop ব্যবহার করে প্যানেল, গ্রিড বা যেকোনো ধরনের র্যাপার (wrapper) কম্পোনেন্ট তৈরি করতে পারো।
import Avatar from "./Avatar.js";
function Card({ children }) {
return <div className="card">{children}</div>;
}
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: "Katsuko Saruhashi",
imageId: "YfeOqp2",
}}
/>
</Card>
);
}
import { getImageUrl } from "./utils.js";
export default function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
export function getImageUrl(person, size = "s") {
return "https://i.imgur.com/" + person.imageId + size + ".jpg";
}
.card {
width: fit-content;
margin: 5px;
padding: 5px;
font-size: 20px;
text-align: center;
border: 1px solid #aaa;
border-radius: 20px;
background: #fff;
}
.avatar {
margin: 20px;
border-radius: 50%;
}
সময়ের সাথে props কীভাবে পরিবর্তিত হয়
একটি কম্পোনেন্ট সময়ের সাথে সাথে বিভিন্ন props
পেতে পারে। Props কেবল শুরুর সময়ের জন্য নয়, বরং যেকোনো মুহূর্তে একটি কম্পোনেন্টের ডেটা কেমন, তা প্রতিফলিত করে।
তবে, Props হলো ইমিউটেবল (immutable), অর্থাৎ অপরিবর্তনীয়। একটি কম্পোনেন্ট নিজে তার props পরিবর্তন করতে পারে না। যখন কোনো পরিবর্তনের প্রয়োজন হয় (যেমন, ব্যবহারকারীর ইনপুটের কারণে), তখন তাকে তার প্যারেন্ট কম্পোনেন্টের কাছে ভিন্ন props পাঠানোর জন্য অনুরোধ করতে হয়।
Props পরিবর্তন করার চেষ্টা করো না। যখন তোমার ইন্টারঅ্যাক্টিভিটির প্রয়োজন হবে, তখন তোমাকে স্টেট (state) ব্যবহার করতে হবে, যা তুমি পরের অধ্যায়ে শিখবে।
সারসংক্ষেপ
- Props পাস করার জন্য সেগুলোকে JSX ট্যাগে HTML অ্যাট্রিবিউটের মতো করে যোগ করো।
- Props পড়ার জন্য
function Component({ prop1, prop2 })
ডিস্ট্রাকচারিং সিনট্যাক্স ব্যবহার করো। size = 100
এভাবে ডিফল্ট মান সেট করা যায়।<Avatar {...props} />
স্প্রেড সিনট্যাক্স দিয়ে সব props ফরওয়ার্ড করা যায়, তবে এটি সাবধানে ব্যবহার করবে।- নেস্টেড JSX, যেমন
<Card><Avatar /></Card>
, প্যারেন্ট কম্পোনেন্টেরchildren
prop হিসেবে পাস হয়। - Props হলো Read-only। ইন্টারঅ্যাক্টিভিটির জন্য তোমাকে স্টেট ব্যবহার করতে হবে।
তোমার জন্য চ্যালেঞ্জ 🧗
১. একটি কম্পোনেন্ট এক্সট্রাক্ট করো
নিচের Gallery
কম্পোনেন্টে দুটি প্রোফাইলের জন্য প্রায় একই রকম মার্কআপ আছে। কোডের পুনরাবৃত্তি কমাতে, একটি Profile
কম্পোনেন্ট এক্সট্রাক্ট করো এবং প্রয়োজনীয় ডেটা props
হিসেবে পাস করো।
import { getImageUrl } from "./utils.js";
export default function Gallery() {
return (
<div>
<h1>Notable Scientists</h1>
<section className="profile">
<h2>Maria Skłodowska-Curie</h2>
<img
className="avatar"
src={getImageUrl("szV5sdG")}
alt="Maria Skłodowska-Curie"
width={70}
height={70}
/>
<ul>
<li>
<b>Profession: </b>
physicist and chemist
</li>
<li>
<b>Awards: 4 </b>
(Nobel Prize in Physics, Nobel Prize in Chemistry, Davy Medal, Matteucci
Medal)
</li>
<li>
<b>Discovered: </b>
polonium (chemical element)
</li>
</ul>
</section>
<section className="profile">
<h2>Katsuko Saruhashi</h2>
<img
className="avatar"
src={getImageUrl("YfeOqp2")}
alt="Katsuko Saruhashi"
width={70}
height={70}
/>
<ul>
<li>
<b>Profession: </b>
geochemist
</li>
<li>
<b>Awards: 2 </b>
(Miyake Prize for geochemistry, Tanaka Prize)
</li>
<li>
<b>Discovered: </b>a method for measuring carbon dioxide in seawater
</li>
</ul>
</section>
</div>
);
}
export function getImageUrl(imageId, size = "s") {
return "https://i.imgur.com/" + imageId + size + ".jpg";
}
.avatar {
margin: 5px;
border-radius: 50%;
min-height: 70px;
}
.profile {
border: 1px solid #aaa;
border-radius: 6px;
margin-top: 20px;
padding: 10px;
}
h1,
h2 {
margin: 5px;
}
h1 {
margin-bottom: 10px;
}
ul {
padding: 0px 10px 0px 20px;
}
li {
margin: 5px;
}