سلام دوستان! توی این پست از مجموعه پست‌های ری‌اکت ۱۰۱ می‌خوایم با چند نکته کاربردی از Props یا همون پراپرتی‌ها توی ری‌اکت آشنا بشیم. قبل از اون بیاید یک آشنایی کلی با این ویژگی داشته باشیم.

 

Props چیه؟ 🤔

Props مخفف Properties و یک ویژگی مهم توی ری‌اکت هست که اجازه میده بین کامپوننت‌های والد و فرزند اطلاعات رد و بدل کنیم. این کار باعث میشه که کامپوننت‌هایی داینامیک و با قابلیت استفاده مجدد (= Reusable) داشته باشیم. همچنین می‌تونیم Encapsulation رو به برنامه بیاریم. هر کامپوننت به این دلیل که فقط با اطلاعات محدود و مشخصی سر و کار داره، باعث میشه برنامه‌ای ماژولار و ایزوله داشته باشیم. این ویژگی رو می‌تونیم به پارامترهای یک تابع تشبیه کنیم:

// function
const counter = (value) => { ... }
counter(10);

// React component
const Counter = ({ value }) => ( ... )
<Counter value={10} />

خب بریم با چند نکته و ترفند درباره پراپرتی‌ها توی ری‌اکت آشنا بشیم 👏

 

نکته‌ها و باید و نبایدهایی درباره پراپرتی‌ها توی ری‌اکت

می‌خوایم با چند نکتهٔ کاربردی از این ویژگی تو ری‌اکت آشنا بشیم:

 

۱. مقادیر پراپرتی‌ها غیر قابل تغییر هستن

مقدار یک پراپرتی نمی‌تونه از داخل کامپوننت تغییر کنه. به قول معروف Immutable و Readonly هستن:

const Counter = (props) => {
  <<props.value = 12;>>

  return <div>{props.value}</div>;
};

export default function App() {
  return (
    <div className="App">
      <Counter value={5} />
      {/* Prints 5, not 12 */}
    </div>
  );
}

توی کد بالا مقدار پراپرتی value رو تغییر دادیم، اما تأثیری روی خروجی نداشت و همون مقدار 5 خط ۱۰ برامون چاپ میشه. البته میشه با ترفند‌هایی مقدار پراپرتی‌ها رو عوض کرد. مثل زمانی که از Destructuring استفاده می‌کنیم. اما به‌طور کلی تغییر دادن مقدار پراپرتی‌ها یک کار غیر استاندارد و Anti-pattern به حساب میاد.

 

۲. از تکنیک Destructuring استفاده کنیم

یکی از راه‌هایی که کمک می‌کنه کدهایی کمتر و خواناتر داشته باشیم استفاده از تکنیک Destructuring هنگام تعریف پراپرتی‌هاست. در حالت عادی هر کامپوننت یک ورودی می‌گیره که یک آبجکت هست که اعضای اون، پراپرتی‌هایی هست که به کامپوننت پاس داده شده:

function Input(props) {
  console.log(props.name);
  console.log(props.type);
}

<Input name="email" type="email" />

اما استفاده از تکنیک Destructuring چند مزیت داره. از جمله اینکه پراپرتی‌ها قبل از استفاده قابل مشاهده هستن (= افزایش خوانایی) و همچنین کاهش کدهای تکراری:

function Input(<<{ name, type }>>) {
  console.log(name);
  console.log(type);
}

<Input name="email" type="email" />

 

۳. به پراپرتی‌ها مقدار پیشفرض بدیم

بهتره برای یک پراپرتی که به‌صورت اختیاری تعریف شده یک مقدار پیشفرض در نظر بگیریم تا هم حجم کدهای کمتری داشته باشیم و هم زمانی که از کامپوننت والد مقداری پاس داده نشد، برنامه دچار خطا نشه:

function Avatar({ src, name = "" }) {
  return <img src={src} alt={name} />
}

 

۴. خودداری از تعریف پراپرتی‌های زیاد

یکی از چیزهایی باعث کاهش خوانایی و کاربردپذیری یک کامپوننت میشه اینه که برای کامپوننت بیش‌از حد پراپرتی تعریف کنیم. حدس اینکه یک کامپوننت که ۱۰ پراپرتی یا بیشتر می‌گیره چه کاری انجام میده راحت نیست. این کار باعث میشه کامپوننت از مسئولیت اصلی خودش فاصله بگیره و مسئول انجام کارهایی بشه که وظیفه اون نیست ( = نقض قانون اول SOLID).

بهتره چنین کامپوننتی رو بشکنیم به کامپوننت‌های کوچیک‌تر تا وظایف کامپوننت‌ها مشخص‌تر و در نتیجه برنامهٔ ما خواناتر و به قول معروف Maintainable بشه.

 

۵. خودداری از Prop Drilling

Prop Drilling به تکنیکی گفته میشه که توی اون برای پاس دادن اطلاعات به یک کامپوننت، اطلاعات باید از لایه‌های زیادی از کامپوننت‌ها عبور کنه (توی قسمت‌های بعدی با این تکنیک آشنا می‌شیم.) یکی از اشکالات این روش اینه که وابستگی بین کامپوننت‌ها رو زیاد و روابط رو پیچیده می‌کنه. برای کامپوننت‌های میانی باید پراپرتی‌هایی رو تعریف کنیم اصلاً بدردشون نمی‌خوره و فقط باید اونها رو عبور بدن. همچنین قابلیت استفاده مجدد از کامپوننت‌ها هم کاهش پیدا می‌کنه.

یک راه بهتر و اصولی برای حل این مشکل استفاده از State Management ها یا Context هست که باعث میشه کامپوننت‌های داخلی به صورت مستقیم به اطلاعات دسترسی داشته باشن.

 

۶. تعریف نوع پراپرتی‌ها

یکی از راه‌های کاهش خطاهای برنامه اینه که نوع پراپرتی‌ها رو هنگام تعریف کامپوننت مشخص کنیم. اگه از جاوااسکریپت استفاده می‌کنیم، می‌تونیم از prop-types استفاده کنیم:

import PropTypes from 'prop-types';

const MyComponent = ({ name }) => <div>Hello, {name}!</div>;

MyComponent.propTypes = {
    name: PropTypes.string.isRequired
};

و اگه از تایپ‌اسکریپت:

type InputProps = {
  value: string;
  name?: string;
  type?: string;
}

const Input = (props: InputProps) => (
  <input {...props} />
)

این کار کمک می‌کنه که هنگام استفاده از این کامپوننت بدونیم چه پراپرتی‌هایی رو در اختیار داریم و نوعشون چی هست، بدون اینکه نگاهی به کدهای کامپوننت بندازیم. همچنین جلوی خیلی از خطاهای Runtime گرفته میشه.

 

۷. استفاده از React.memo

همونطور که می‌دونیم، با Re-render شدن کامپوننت والد، کامپوننت‌های فرزند همگی Re-render میشن. استفاده از React.memo باعث میشه که کامپوننت فرزند فقط زمانی Re-render بشه که مقدار پراپرتی‌هایی که از کامپوننت والد به اون پاس داده شده تغییر کنه:

import { memo } from 'react';


const MyComponent = (props) => (...);

export default <<memo(MyComponent);>>

اگه کامپوننت پیچیده و سنگینی داریم، استفاده از این روش باعث بهبود سرعت و کیفیت کامپوننت و برنامه میشه. بدون استفاده از React.memo، هر بار که کامپوننت والد  Re-render میشه، در هر صورت کامپوننت فرزند هم Re-render بشه.

 

خب دوستان امیدوارم از اطلاعاتی که بررسی کردیم استفاده کرده باشین. توی قسمت‌های بعدی با نکات کاربردی‌تر و جالب‌تری از ری‌اکت آشنا می‌شیم ✌️😉