কম্পোনেন্টে প্রপস পাস করা

React কম্পোনেন্টগুলো props ব্যবহার করে একে অপরের সাথে যোগাযোগ করে। প্রতিটি parent কম্পোনেন্ট তার child কম্পোনেন্টগুলোকে props দিয়ে কিছু তথ্য পাঠাতে পারে। Props HTML attributes-এর মত মনে হতে পারে, তবে আপনি এর মাধ্যমে object, array এবং function সহ যেকোনো JavaScript মান পাঠাতে পারেন।

যা যা আপনি শিখবেন

  • কীভাবে একটি কম্পোনেন্টে props পাঠাতে হয়
  • কীভাবে একটি কম্পোনেন্ট থেকে props পড়তে হয়
  • কীভাবে props-এর জন্য default মান নির্দিষ্ট করতে হয়
  • কীভাবে একটি কম্পোনেন্টে কিছু JSX পাঠাতে হয়
  • কীভাবে সময়ের সাথে সাথে props পরিবর্তিত হয়

সুপরিচিত props

প্রপস হলো সেই তথ্য যা আপনি একটি JSX ট্যাগে পাঠান। উদাহরণস্বরূপ, className, src, alt, width, এবং height হল কিছু প্রপস, যা আপনি একটি <img> ট্যাগে পাঠাতে পারেন।

function Avatar() {
  return (
    <img
      className="avatar"
      src="https://i.imgur.com/1bX5QH6.jpg"
      alt="Lin Lanying"
      width={100}
      height={100}
    />
  );
}

export default function Profile() {
  return (
    <Avatar />
  );
}

আপনি যে প্রপসগুলো <img> ট্যাগে পাঠাতে পারেন, সেগুলো পূর্বনির্ধারিত (ReactDOM HTML স্ট্যান্ডার্ড-এর সাথে সামঞ্জস্যপূর্ণ)। তবে আপনি নিজের কম্পোনেন্টগুলো, যেমন <Avatar>,-এ যেকোনো প্রপস পাঠাতে পারেন তাদের কাস্টমাইজ করার জন্য। এটি কীভাবে করবেন, দেখুন!

একটি কম্পোনেন্টে প্রপস পাঠানো

এই কোডে, Profile কম্পোনেন্টটি এর চাইল্ড কম্পোনেন্ট Avatar-এ কোনো প্রপস পাঠাচ্ছে না:

export default function Profile() {
return (
<Avatar />
);
}

আপনি দুটি ধাপে Avatar-এ কিছু props দিতে পারেন।

ধাপ ১: child কম্পোনেন্টে props পাঠানো

প্রথমে, কিছু প্রপস Avatar-এ পাঠান। উদাহরণস্বরূপ, দুটি প্রপস পাঠানো যাক: person (একটি অবজেক্ট), এবং size (একটি সংখ্যা):

export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}

খেয়াল করুন

যদি person= এর পর ডাবল কার্লি ব্রেস আপনাকে বিভ্রান্ত করে, মনে রাখুন এগুলো কেবল একটি অবজেক্ট JSX-এর কার্লি ব্রেসের ভিতরে।

এখন আপনি এই props Avatar কম্পোনেন্টের ভিতরে পড়তে পারেন।

ধাপ ২: চাইল্ড কম্পোনেন্টের ভেতরে প্রপস পড়ুন

আপনি function Avatar-এর ঠিক পরে ({ এবং }) এর ভিতরে props-এর নামগুলো কমা দিয়ে আলাদা করে লিখে এই props পড়তে পারেন। এভাবে, আপনি সেগুলোকে ভেরিয়েবলের মত ব্যবহার করতে পারেন।

function Avatar({ person, size }) {
// person and size are available here
}

person এবং size props ব্যবহার করে Avatar-এ কিছু logic যোগ করুন, আর আপনার কাজ শেষ।

এখন আপনি বিভিন্ন props-এর সাথে Avatar-কে বিভিন্ন উপায়ে রেন্ডার করতে পারেন। মান পরিবর্তন করে দেখুন!

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>
  );
}

প্রপস আপনাকে প্যারেন্ট এবং চাইল্ড কম্পোনেন্টগুলোকে স্বাধীনভাবে ভাবতে সাহায্য করে। উদাহরণস্বরূপ, আপনি Profile-এর মধ্যে person বা size প্রপস পরিবর্তন করতে পারেন, Avatar কীভাবে সেগুলো ব্যবহার করে তা নিয়ে চিন্তা না করেই। একইভাবে, আপনি Avatar-এ প্রপসগুলো কীভাবে ব্যবহৃত হচ্ছে তা পরিবর্তন করতে পারেন, Profile-এর দিকে না তাকিয়েই।

আপনি প্রপসকে “নব” বা নিয়ন্ত্রণ কাঁটা হিসেবে ভাবতে পারেন যা আপনি সামঞ্জস্য করতে পারেন। এগুলো আসলে ফাংশনের আর্গুমেন্টের মতো কাজ করে—আসলে, প্রপস হচ্ছে আপনার কম্পোনেন্টের একমাত্র আর্গুমেন্ট! React কম্পোনেন্ট ফাংশনগুলো একটি মাত্র আর্গুমেন্ট, অর্থাৎ একটি প্রপস অবজেক্ট গ্রহণ করে।

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

সাধারণত আপনাকে সম্পূর্ণ props object প্রয়োজন হয় না, তাই আপনি এটি আলাদা props এ ভেঙে ফেলেন।

সতর্কতা

প্রপস ডিক্লেয়ার করার সময় { এবং } জোড়া মিস করবেন না ( এবং ) এর ভেতরে:

function Avatar({ person, size }) {
// ...
}

এই সিনট্যাক্সটিকে “ডিস্ট্রাকচারিং” বলা হয় এবং এটি ফাংশন প্যারামিটার থেকে প্রপার্টি পড়ার সমতুল্য।

function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}

প্রপের জন্য একটি ডিফল্ট মান নির্ধারণ করা

যদি আপনি কোনো প্রপের জন্য ডিফল্ট মান নির্ধারণ করতে চান, যাতে কোনো মান নির্দিষ্ট না থাকলে তা প্রযোজ্য হয়, তাহলে ডিস্ট্রাকচারিংয়ে প্যারামিটারের পরে = এবং ডিফল্ট মানটি যোগ করতে পারেন:

function Avatar({ person, size = 100 }) {
// ...
}

এখন, যদি <Avatar person={...} /> কোনো size প্রপ ছাড়া রেন্ডার করা হয়, তাহলে size সেট হবে 100

ডিফল্ট মানটি কেবল তখনই ব্যবহৃত হবে যদি size প্রপটি অনুপস্থিত থাকে অথবা আপনি size={undefined} পাঠান। তবে, যদি আপনি size={null} বা size={0} পাঠান, তাহলে ডিফল্ট মান ব্যবহৃত হবে না

JSX স্প্রেড syntax এর সাথে props ফরোয়ার্ড করা

কখনও কখনও, props পাঠানো খুবই পুনরাবৃত্তিমূলক হতে পারে:

function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}

পুনরাবৃত্তিমূলক কোডে কোনো সমস্যা নেই—এটি আরও বোধগম্য হতে পারে। কিন্তু কখনও কখনও আপনি সংক্ষিপ্ততা মূল্যায়ন করতে পারেন। কিছু কম্পোনেন্ট তাদের সমস্ত props child কম্পোনেন্টে ফরোয়ার্ড করে, যেমন Profile Avatar-এর সাথে করে। যেহেতু তারা কোনো props সরাসরি ব্যবহার করে না, তাই একটি সংক্ষিপ্ত “স্প্রেড” syntax ব্যবহার করা যেতে পারে:

function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}

এটি Profile এর সমস্ত props Avatar এ ফরোয়ার্ড করে কোনো নাম তালিকা ছাড়াই।

স্প্রেড syntax নিয়ন্ত্রণের সাথে ব্যবহার করুন। যদি আপনি এটি প্রতিটি কম্পোনেন্টে ব্যবহার করেন, তাহলে কিছু সমস্যা রয়েছে। সাধারণত, এটি নির্দেশ করে যে আপনাকে আপনার কম্পোনেন্টগুলো ভাগ করা উচিত এবং children JSX হিসেবে পাঠানো উচিত।

children হিসেবে JSX পাঠানো

বিল্ট-ইন ব্রাউজার ট্যাগ নেস্ট করা সাধারণ:

<div>
<img />
</div>

আপনার নিজস্ব কম্পোনেন্টগুলো একইভাবে নেস্ট করতে পারেন:

<Card>
<Avatar />
</Card>

যখন আপনি একটি JSX ট্যাগের ভিতরে কন্টেন্ট নেস্ট করেন, parent কম্পোনেন্ট সেই কন্টেন্টকে একটি children prop-এ গ্রহণ করবে। উদাহরণস্বরূপ, নিচের Card কম্পোনেন্ট একটি children prop গ্রহণ করবে যেটি <Avatar /> সেট করা আছে এবং এটি একটি wrapper div এ রেন্ডার করবে:

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>
  );
}

Card-এর ভিতরে <Avatar> পরিবর্তন করে কিছু টেক্সট যোগানোর চেষ্টা করুন এবং দেখুন কীভাবে Card যেকোনো নেস্টেড কন্টেন্টকে র‍্যাপ করতে পারে। এটি জানে না যে এর ভিতরে কী রেন্ডার করা হচ্ছে। আপনি এই নমনীয় pattern অনেক জায়গায় দেখতে পাবেন।

একটি children prop সহ কম্পোনেন্টকে এমন একটি “ছিদ্র” হিসেবে ভাবতে পারেন যা parent কম্পোনেন্টগুলো যেকোনো JSX দিয়ে “পূর্ণ” করতে পারে। আপনি ভিজ্যুয়াল wrapper-দের জন্য children prop প্রায়ই ব্যবহার করবেন: প্যানেল, গ্রিড ইত্যাদি।

A puzzle-like Card tile with a slot for "children" pieces like text and Avatar

Illustrated by Rachel Lee Nabors

How props change over time

নিচের Clock কম্পোনেন্টটি parent কম্পোনেন্ট থেকে দুটি props গ্রহণ করে: color এবং time। (parent কম্পোনেন্টের কোডটি বাদ দেওয়া হয়েছে কারণ এটি state ব্যবহার করে, যা আমরা এখনো আলোচনা করছি না।)

নীচের সিলেক্ট বক্সে রং পরিবর্তন করার চেষ্টা করুন:

export default function Clock({ color, time }) {
  return (
    <h1 style={{ color: color }}>
      {time}
    </h1>
  );
}

এই উদাহরণটি দেখায় যে একটি কম্পোনেন্ট সময়ের সাথে সাথে বিভিন্ন প্রপস পেতে পারে। প্রপস সর্বদা স্থির নয়! এখানে, time প্রপ প্রতি সেকেন্ডে পরিবর্তিত হয়, এবং color প্রপটি যখন আপনি অন্য রঙ নির্বাচন করেন তখন পরিবর্তিত হয়। প্রপস যেকোনো সময়ে একটি কম্পোনেন্টের ডেটা প্রতিফলিত করে, শুধুমাত্র শুরুতে নয়।

তবে, প্রপস অপরিবর্তনীয়—এটি একটি কম্পিউটার বিজ্ঞান সম্পর্কিত শব্দ যার অর্থ “অপরিবর্তনীয়”। যখন একটি কম্পোনেন্ট তার প্রপস পরিবর্তন করতে চায় (যেমন, ব্যবহারকারীর একটি ক্রিয়ার প্রতিক্রিয়া হিসেবে বা নতুন ডেটার জন্য), তখন এটি তার প্যারেন্ট কম্পোনেন্টকে বিভিন্ন প্রপস—একটি নতুন অবজেক্ট পাঠানোর জন্য “বিনীত” করবে! তারপর তার পুরানো প্রপস বাদ দেওয়া হবে, এবং অবশেষে জাভাস্ক্রিপ্ট ইঞ্জিন তাদের দ্বারা নেওয়া মেমরি পুনরুদ্ধার করবে।

“প্রপস পরিবর্তন করার চেষ্টা করবেন না”। যখন আপনাকে ব্যবহারকারীর ইনপুটের প্রতিক্রিয়া জানাতে হবে (যেমন নির্বাচিত রঙ পরিবর্তন করা), তখন আপনাকে “স্টেট সেট” করতে হবে, যা আপনি স্টেট: একটি কম্পোনেন্টের মেমরি থেকে শিখতে পারেন।

পুনরালোচনা

  • প্রপস পাঠাতে, সেগুলো JSX-এ যুক্ত করুন, যেমন আপনি HTML অ্যাট্রিবিউটগুলোর সাথে করেন।
  • প্রপস পড়তে, function Avatar({ person, size }) ডিস্ট্রাকচারিং সিনট্যাক্স ব্যবহার করুন।
  • আপনি একটি ডিফল্ট মান নির্ধারণ করতে পারেন যেমন size = 100, যা অনুপস্থিত এবং undefined প্রপসের জন্য ব্যবহৃত হয়।
  • আপনি সমস্ত প্রপসকে <Avatar {...props} /> JSX স্প্রেড সিনট্যাক্সের মাধ্যমে ফরওয়ার্ড করতে পারেন, তবে এটিকে অতিরিক্ত ব্যবহার করবেন না!
  • নেস্টেড JSX যেমন <Card><Avatar /></Card> Card কম্পোনেন্টের children প্রপ হিসেবে উপস্থিত হবে।
  • প্রপস হল সময়ের একটি রিড-অনলি স্ন্যাপশট: প্রতিটি রেন্ডারে প্রপসের একটি নতুন সংস্করণ পাওয়া যায়।
  • আপনি প্রপস পরিবর্তন করতে পারবেন না। যখন আপনাকে ইন্টারঅ্যাকটিভিটি প্রয়োজন, তখন আপনাকে স্টেট সেট করতে হবে।

চ্যালেঞ্জ 1 / 3:
একটি কম্পোনেন্ট বের করুন

এই Gallery কম্পোনেন্টে দুটি প্রফাইলের জন্য কিছু খুব অনুরূপ মার্কআপ রয়েছে। ডুপ্লিকেশন কমানোর জন্য একটি Profile কম্পোনেন্ট বের করুন। আপনাকে এটি কী প্রপস পাঠাতে হবে তা নির্বাচন করতে হবে।

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>
  );
}