کامپوننتهای React برای گفتگو و انتقال اطلاعات با یکدیگر از ابزاری به نام پروپها (Props) استفاده میکنند. هر کامپوننت والد (Parent) میتواند اطلاعاتی را در قالب Props به کامپوننتهای فرزند (Child) خود پاس دهد. پروپها شما را به یاد ویژگیهای (Attributes) تگهای HTML میاندازند، اما تفاوت بزرگشان این است که در راکت میتوانید هر نوع مقدار جاوااسکریپتی (از جمله اشیاء، آرایهها، توابع و حتی کدهای JSX) را از طریق آنها منتقل کنید.
نحوه پاس دادن و خواندن پروپها در کامپوننت
تعیین مقدار پیشفرض (Default Value) برای پروپها
استفاده از پروپ جادویی children برای پاس دادن کدهای JSX
درک دلیل غیرقابل تغییر بودن (Immutable) پروپها
زمانی که از تگهای استاندارد مرورگر مثل <img> استفاده میکنید، ویژگیهایی مثل className، src و width را به آن پاس میدهید. اینها پروپهای پیشفرض و استاندارد HTML هستند:
<img className="avatar" src="image.jpg" alt="Lin Lanying" width={100} />
اما جذابیت داستان اینجاست که برای کامپوننتهای دستساز خودتان (مثلاً کامپوننت <Avatar />) میتوانید پروپهای کاملاً سفارشی و دلخواه تعریف کنید. این فرآیند ۲ گام ساده دارد:
در کامپوننت والد (Profile)، پروپهای دلخواهی مانند person (که یک شیء است) و size (که یک عدد است) را به فرزند اضافه میکنیم:
export default function Profile() {
return (
<Avatar
person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }}
size={100}
/>
);
}
برای خواندن این اطلاعات، نام پروپها را درون یک آکولااد { } مستقیماً داخل ورودی تابع کامپوننت فرزند قرار میدهید. حالا این مقادیر مانند متغیرهای معمولی داخل تابع در دسترس هستند:
// utils.js شامل منطق ساخت آدرس عکس است
import { getImageUrl } from './utils.js';
function Avatar({ person, size }) {
return (
<img
className="avatar"
src={getImageUrl(person)}
alt={person.name}
width={size}
height={size}
/>
);
}
💡 مزیت بزرگ: پروپها به شما اجازه میدهند به کامپوننتهای والد و فرزند به صورت کاملاً مستقل فکر کنید. شما میتوانید مقدار
sizeرا در فایل والد تغییر دهید، بدون اینکه نگران باشید داخل کامپوننتAvatarچه کدهایی نوشته شده است.
در واقعیت، توابع کامپوننت در راکت تنها یک آرگومان ورودی میپذیرند که یک «شیء حاوی تمام پروپها» یا همان Props Object است:
// ساختار سنتی جاوااسکریپت
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
از آنجا که معمولاً به کل شیء props نیازی نداریم، از سینتکس تجزیه شیء یا اصطلاحاً Destructuring استفاده میکنیم تا مستقیماً به ویژگیهای داخل آن دسترسی داشته باشیم:
// ⚠️ تله: آکولااد درون پرانتز ورودی را فراموش نکنید!
function Avatar({ person, size }) {
// ...
}
اگر تمایل دارید که در صورت پاس ندادن یک پروپ، کامپوننت از یک مقدار جایگزین استفاده کند، میتوانید در زمان تفکیک ورودیها، با علامت = مقدار پیشفرض را مشخص کنید:
function Avatar({ person, size = 100 }) {
// اگر والد پروپ size را نفرستد، مقدار آن به طور خودکار 100 خواهد بود
}
نکته: مقدار پیشفرض تنها زمانی فعال میشود که پروپ فرستاده نشده باشد یا مقدار آن صراحتاً size={undefined} باشد. اگر مقدار null یا 0 پاس داده شود، مقدار پیشفرض اعمال نخواهد شد.
... Spread Syntax)گاهی اوقات پاس دادن تکتک پروپها در کامپوننتهای واسط روتین و تکراری میشود:
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar person={person} size={size} isSepia={isSepia} thickBorder={thickBorder} />
</div>
);
}
اگر کامپوننت واسط (Profile) خودش مستقیماً با این پروپها کاری ندارد و فقط میخواهد آنها را تمام و کمال به فرزندش بسپارد، میتوانید از نحو سه نقطه جاوااسکریپت بهره ببرید:
function Profile(props) {
return (
<div className="card">
<Avatar {...props} /> {/* تمام پروپها یکجا فوروارد میشوند */}
</div>
);
}
توصیه حرفهای: در استفاده از این استایل خسیس باشید! زیادهروی در Spread کردن پروپها خوانایی پروژه را کم میکند و نشان میدهد که شاید بهتر است کامپوننت خود را به بخشهای کوچکتر تقسیم کنید.
childrenهمانطور که تگهای HTML را درون هم میچینید، میتوانید کامپوننتهای خود را نیز به صورت تودرتو بنویسید:
<Card>
<Avatar />
</Card>
هر زمانی که محتوایی را درون تگ یک کامپوننت سفارشی قرار میدهید، آن کامپوننت والد محتوای داخلی را در پروپی به نام children دریافت میکند. کامپوننت والد اصلاً نیازی ندارد بداند چه چیزی درونش رندر میشود؛ او فقط مانند یک قاب عمل میکند:
// Card.js
export default function Card({ children }) {
return (
<div className="card-wrapper">
{children} {/* کامپوننت Avatar یا هر متن دیگری اینجا تزریق میشود */}
</div>
);
}
این الگو که به آن اصطلاحاً وجود یک «حفره» (Hole) در کامپوننت میگویند، برای ساخت عناصر بصری نگهدارنده مثل پنلها، باکسهای کارت، و گریدها فوقالملعاده منعطف و کاربردی است.
پروپها پویا هستند و میتوانند در طول زمان تغییر کنند (مثلاً کامپوننت ساعتی که هر ثانیه زمان جدیدی را به عنوان پروپ دریافت میکند). اما یک قانون سفتوسخت علمی در راکت وجود دارد: پروپها غیرقابل تغییر (Immutable) یا اصطلاحاً Read-Only هستند.
وقتی یک کامپوننت نیاز دارد پروپهای خود را در پاسخ به رفتار کاربر تغییر دهد، حق ندارد رفرنس پروپ دریافتی را دستکاری کند:
// 🔴 اشتباه محض: هرگز پروپها را مستقیماً دستکاری نکنید!
props.size = 200;
کامپوننت فرزند باید مودبانه از والد خود «درخواست» کند تا یک شیء پروپ جدید برایش بفرستد. این کار از طریق سیستم مدیریت حافظه یا همان State (وضعیت) انجام میشود که در درسهای بعدی به دنیای شگفتانگیز آن قدم خواهیم گذاشت.
برای پاس دادن پروپ، آنها را مانند ویژگیهای HTML به تگ JSX اضافه کنید.
برای خواندن پروپها، از سینتکس تفکیک ورودی تابع یعنی function Avatar({ size }) استفاده کنید.
میتوانید با علامت = مقدار پیشفرض برای زمانهای غیبت یک پروپ تعیین کنید.
کدهای تودرتو در قالب پروپ جادویی و قدرتمند children به کامپوننت والد تحویل داده میشوند.
پروپها تصاویر ثبتشده در زمان (Snapshots) و غیرقابل تغییر هستند؛ هر رندر نسخه تازهای از پروپها را بازخوانی میکند.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://react.dev/learn