API سطح بالای React

React نقطه‌ی ورود به کتابخانه‌ی ری‌اکت است. اگر شما React را از تگ <script> بارگذاری کنید، این APIهای سطح بالا از React گلوبال قابل دسترسی هستند. اگر شما از ES6 ‌به‌همراه npm استفاده می‌کنید، می‌توانید بنویسید import React from 'react'. اگر از ES5 به‌همراه npm استفاده می‌کنید، می‌توانید بنویسید var React = require('react').

مرور کلی

کامپوننت‌ها

کامپوننت‌های ری‌اکت به شما اجازه می‌دهند تا رابط کاربری را به بخش‌های مستقل با قابلیت استفاده‌ی مجدد تقسیم کنید، و درمورد هر قسمت به صورت جداگانه فکر کنید. کامپوننت‌های ری‌اکت را می‌توان به عنوان زیرکلاسی برای React.Component یا React.PureComponent تعریف کرد.

اکر شما از کلاس‌های ES6 استفاده نمی‌کنید، می‌توانید به جای آن از create-react-class استفاده کنید. بخش ری‌اکت بدون استفاده از ES6 را برای آگاهی بیشتر ببینید.

کامپوننت‌های ری‌اکت می‌توانند به شکل تابع نیز تعریف شوند که می‌توان آن‌ها را با memo بسته‌بندی (wrap) کرد:

ایجاد المنت‌های ری‌اکت

ما پیشنهاد می‌کنیم برای توصیف رابط کاربری از JSX استفاده کنید. هر المنت JSX یک Syntactic sugar است برای صدا زدن ()React.createElement. اگر از JSX استفاده کنید، معمولا متدهای زیر را به شکل مستقیم فراخوانی نخواهید کرد.

برای آگاهی بیشتر از بخش ری‌اکت بدون استفاده از JSX دیدن کنید.

تبدیل المنت‌ها

React، چندین API برای دست‌کاری کردن المنت‌ها فراهم می‌کند:

فرگمنت‌ها

React همچنین برای یک کامپوننت، امکان رندر کردن چند المنت بدون استفاده از wrapper را فراهم می‌سازد.

Refs

تعلیق (Suspense)

Suspense به کامپوننت‌ها اجازه می‌دهد تا قبل از رندر شدن، برای چیزی «صبر» کنند. فعلا Suspense فقط یک مورد کاربرد را پشتیبانی می‌کند: بارگذاری پویای کامپوننت‌ها با استفاده از React.lazy. در آینده، از مورد کاربردهای دیگری چون واکشی داده (data fetching) پشتیبانی خواهد کرد.

هوک‌ها

هوک‌ها یک افزونه جدید در ری‌اکت ۱۶.۸ هستند. آن‌ها به شما این توانایی را می‌دهند که بدون نوشتن کلاس از state بهره ببرید. هوک‌ها یک بخش توضیحات جدا و یک مرجع API جدا دارند:


مرجع

React.Component

React.Component کلاس پایه است برای کامپوننت‌های ری‌اکت وقتی به روش کلاس‌های ES6 تعریف شده باشند:

class Greeting extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

مرجع React.Component API را برای لیستی از متدها و ویژگی‌های مربوط به کلاس پایه React.Component ببینید.


React.PureComponent

React.PureComponent به React.Component شبیه است. تفاوت آن‌ها این است که React.Component تابع ()shouldComponentUpdate را پیاده‌سازی نمی‌کند، ولی React.PureComponent آن‌را با یک قیاس سطحی props و state پیاده‌سازی می‌کند.

اگر تابع render() کامپوننت ری‌اکت شما، در صورت یکسان بودن props و state، خروجی یکسان تولید می‌کند، برای ارتقای کارایی در برخی از موارد می‌توانید از React.PureComponent استفاده کنید.

نکته

shouldComponentUpdate() در React.PureComponent فقط به صورت سطحی (shallow) اشیاء را مقایسه می‌کند. اگر این اشیاء دارای ساختاری پیچیده باشند، ممکن است باعث رخ‌داد منفی کاذب(false-negative) برای تفاوت‌های عمیق‌تر شود. تنها زمانی PureComponent را extend کنید که توقع دارید state و props ساده‌ باشند، یا زمانی از ()forceUpdate استفاده کنید که می‌دانید ساختار عمیق داده‌ها تغییر پیدا کرده است. و یا داده‌های تغییرناپذیز را برای تسهیل مقایسه سریع داده‌های تودرتو استفاده کنید.

علاوه بر این، shouldComponentUpdate() در React.PureComponent، به‌روز شدن state و props را در کل زیردرخت کامپوننت درنظر نمی‌گیرد. پس مطمئن شوید که همه‌ی کامپوننت‌های فرزند نیز «pure» باشند.


React.memo

const MyComponent = React.memo(function MyComponent(props) {
  /* render using props */
});

React.memo یک کامپوننت مرتبه بالا می‌باشد. شبیه بهReact.PureComponent است ولی برای توابع به جای کلاس‌ها استفاده می‌شود.

اگر کامپوننت تابعی شما در صورت گرفتن props یکسان، نتیجه‌ی یکسان تولید می‌کند، می‌توانید آن‌را در یک فراخوانی React.memo، wrap کنید تا با یادداشت‌برداری نتیجه، کارایی را بالا برید. این کار به آن معناست که ری‌اکت رندر کردن کامپوننت را در نظر نمی‌گیرد و آخرین نتایج رندرهای قبلی را درنظر می‌گیرد.

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

function MyComponent(props) {
  /* render using props */
}
function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}
export default React.memo(MyComponent, areEqual);

این روش فقط به عنوان بهینه‌سازی کارایی مورد استفاده است. برای «جلوگیری» از رندر، از آن استفاده نکنید، به خاطر آن‌که می‌تواند به خطا سرانجام یابد.

نکته:

برخلاف متد ()shouldComponentUpdate در کامپوننت‌های به شکل کلاس، تابعareEqual مقدار true را بازمی‌گرداند اگر propها یکسان باشند و false برمیگرداند اگر propها متفاوت باشند. این رفتاری عکس shouldComponentUpdateمی‌باشد.


()createElement

React.createElement(
  type,
  [props],
  [...children]
)

ایجاد و برگرداندن یک المنت ری‌اکت جدید با توجه به نوع (type) داده شده. آرگومان نوع داده شده می‌تواند رشته‌ی نام یک تگ (مثل 'div' یا 'span')، یک نوع کامپوننت ری‌اکت (کلاس یا تابع)، یا یک نوع فرگمنت ری‌اکت باشد.

کد نوشته شده با JSX تبدیل به حالتی می‌شود که از React.createElement() استفاده کند. شما در حالت معمول اگر از JSX استفاده کنید به صورت مستقیم React.createElement() را فرا نمی‌خوانید. ری‌اکت بدون استفاده از JSX را برای یادگیری بیشتر ببینید.


()cloneElement

React.cloneElement(
  element,
  [props],
  [...children]
)

شبیه‌سازی (clone) و برگرداندن یک المنت به عنوان یک نقطه شروع. المنت جدید، دارای props المنت اصلی همراه با props جدید به شکل ترکیب شده سطحی می‌باشد. فرزندان جدید جایگزین فرزندان قبلی می‌شوند. key و ref المنت اصلی محفوظ می‌مانند.

React.cloneElement() تقریبا برابر است با:

<element.type {...element.props} {...props}>{children}</element.type>

گرچه، این کار refها را محفوظ نگاه می‌دارد. این یه آن معناست که اگر شما یک فرزند را با ref آن دریافت کنید، آن‌را به شکل اتفاقی از اجداد خود سرقت نمی‌کنید. شما ref یکسان متصل شده به المنت جدید خواهید داشت.

این API به عنوان جایگزینی برای React.addons.cloneWithProps() منسوخ شده معرفی شد.


()createFactory

React.createFactory(type)

یک تابع برمی‌گرداند که المنت‌های ری‌اکت با نوع داده شده را تولید می‌کند. مثل ()React.createElement، آرگومان نوع داده شده می‌تواند رشته‌ی نام یک تگ (مثل 'div' یا 'span')، یک نوع کامپوننت ری‌اکت (کلاس یا تابع)، یا یک نوع فرگمنت ری‌اکت باشد.

این helper یک نوع قدیمی(legacy) محسوب می‌شود و ما شما را تشویق می‌کنیم که به صورت مستقیم از React.createElement() یا JSX استفاده کنید.

اگر از JSX استفاده کنید، معمولا React.createFactory() را مستقیما فراخوانی نخواهید کرد. ری‌اکت بدون استفاده از JSX را برای یادگیری بیشتر ببینید.


()isValidElement

React.isValidElement(object)

بررسی میکند که آیا شیء مورد نظر، المنت ری‌اکت هست یا خیر. true یا false برمی‌گرداند.


React.Children

React.Children ابزاری برای کار با ساختمان‌داده‌ی غیرشفافthis.props.children فراهم می‌کند.

React.Children.map

React.Children.map(children, function[(thisArg)])

یک تابع روی هر فرزند immediate داخل children فرامی‌خواند که this را به عنوان thisArg تنظیم می‌کند. اگر children یک آرایه باشد از آن میگذرد و تابع روی تک‌تک فرزند‌های درون آرایه اجرا می‌شود. اگر children، null یا undefined باشد، این متد به جای یک آرایه، null یا undefined برمی‌گرداند.

نکته:

اگر children، یک فرگمنت باشد به عنوان یک فرزند تنها با آن برخورد می‌شود و از آن نمی‌گذرد.

React.Children.forEach

React.Children.forEach(children, function[(thisArg)])

مانند ()React.Children.map است ولی آرایه‌ای برنمی‌گرداند.

React.Children.count

React.Children.count(children)

تعداد کامپوننت‌های موجود در children را برمی‌گرداند، برابر تعداد دفعاتی است که callback داده شده به map یا forEach فراخوانی شده است.

React.Children.only

React.Children.only(children)

بررسی می‌کند که آیا children فقط یک فرزند (المنت ری‌اکت) دارد و آن را برمی‌گرداند. در غیراین‌صورت این متد یک ارور برمی‌گرداند.

نکته:

React.Children.only()، مقدار برگردانده شده توسط ()React.Children.map را قبول نمی‌کند زیرا یک آرایه است نه یک المنت ری‌اکت.

React.Children.toArray

React.Children.toArray(children)

ساختمان‌ داده‌ی غیرشفاف children را به شکل یک آرایه‌ی مسطح با فرزندهایی که به هرکدام یک کلید اختصاص ‌داده شده برمی‌گرداند. کاربردی است اگر بخواهید مجموغه‌هایی از فرزندان را در متدهای رندر خود دستکاری کنید، مخصوصا اگر بخواهید this.props.children را قبل از پاس دادن به سطوح پایین‌تر، قطعه‌قطعه یا دوباره مرتب کنید.

نکته:

React.Children.toArray() در فرایند مسطح‌سازی لیست فرزندان، کلیدها را تغییر می‌دهد تا معنای آرایه‌های تودرتو حفظ شود. به این معنا که، toArray، هر کلید را پیشوندگذاری می‌کند تا کلید هر المنت به‌‌ همان آرایه‌ی واردشده‌ای محدود شود که دارای آن کلید بوده است .


React.Fragment

کامپوننت React.Fragment به شما این توانایی را می‌دهد تا چندین المنت را در متد render() برگردانید، بدون آن‌که المنت DOM جدیدی بسازید:

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}

همچنین می‌توانید آن را به شکل خلاصه‌ی <></> نمایش دهید. برای آگاهی بیشتر، ری‌اکت نسخه‌ی 16.2.0: پشتیبانی ارتقا یافته از فرگمنت‌ها را ببینید.

React.createRef

React.createRef یک ref می‌سازد که می‌تواند با استفاده از خصوصیت ref به المنت متصل شود.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);

    this.inputRef = React.createRef();
  }

  render() {
    return <input type="text" ref={this.inputRef} />;
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }
}

React.forwardRef

React.forwardRef یک کامپوننت ری‌اکت ایجاد می‌کند که خصوصیت ref دریافت شده را به کامپوننت زیرین در درخت فوروارد کند. این روش خیلی معمول نیست مگر در دو مورد:

React.forwardRef، یک تابع رندرکننده را به عنوان آرگومان می‌پذیرد. ری‌اکت این تابع را با props و ref به عنوان دو آرگومان صدا می‌زند. این تابع باید یک نود ری‌اکت برگرداند.

const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

در مثال بالا، ری‌اکت، ref داده شده به المنت <FancyButton ref={ref}> را به عنوان آرگومان دوم به تابع رندرکننده صدازده‌ شده درون React.forwardRef می‌دهد. این تابع رندرکننده، ref را به المنت <button ref={ref}> انتقال می‌دهد.

در نتیجه، بعد از این‌که ری‌اکت، ref را متصل کرد، ref.current مستقیما به المنت DOM مربوط به <button> اشاره می‌کند.

برای آگاهی بیشتر، فوروارد refها را ببینید.

React.lazy

React.lazy() به شما اجازه می‌دهد کامپوننتی تعریف کنید که به شکل پویا بارگذاری می‌شود. این کمک می‌کند تا حجم بسته‌ی نهایی(bundle) کاهش یابد تا بارگذاری کامپوننت‌هایی که در رندر ابتدایی استفاده نشده‌اند را به تعویق اندازد.

می‌توانید برای یادگیری نحوه‌ی استفاده از آن به سند بخش‌بندی کد بروید. ممکن است بخواهید این مقاله را بررسی کنید، که در مورد چگونگی استفاده از آن با جزئیاتی بیشتر توضیح داده است .

// این کامپوننت به صورت پویا بارگذاری می‌شود
const SomeComponent = React.lazy(() => import('./SomeComponent'));

توجه کنید که کامپوننت‌های lazy نیازمند وجود یک کامپوننت <React.Suspense> در سطوح بالاتر درخت رندر هستند. این نحوه‌ی مشخص کردن یک loading indicator است.

نکته

استفاده از React.lazyهمراه با import پویا نیازمند آن است که Promiseها در محیط جاوااسکریپت قابل استفاده باشند. این نیازمند یک polyfill روی IE11 و کمتر از آن است.

React.Suspense

React.Suspense به شما اجازه می‌دهد loading indicator را مشخص کنید در حالتی که برخی کامپوننت‌های زیرین آن در درخت هنوز آماده‌ی رندر نباشند. فعلا، کامپوننت‌های با بارگذاری lazy، تنها مورد کاربردی است که <React.Suspense> از آن پشتیبانی می‌کند:

// این کامپوننت به صورت پویا بارگذاری می‌شود
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    // Displays <Spinner> until OtherComponent loads
    <React.Suspense fallback={<Spinner />}>
      <div>
        <OtherComponent />
      </div>
    </React.Suspense>
  );
}

این قسمت در راهنمای بخش‌بندی کد توضیح داده شد‌ه‌است. توجه کنید که کامپوننت‌های lazy می‌توانند در اعماق یک درخت Suspense موجود باشند (نیازی نیست که تک‌تک آن‌ها را به این شکل wrap کنید) . بهترین تمرین این است که <Suspense> را جایی قرار دهید که میخواهید یک loading indicator مشاهده کنید، اما lazy() را جایی قرار دهید که می‌خواهید کد را بخش‌بندی کنید.

گرچه این امکان فعلا وجود ندارد، در آینده برنامه‌ریزی کرده‌ایم که به Suspense اجازه دهیم تا به سناریوهای دیگری چون واکشی داده رسیدگی کند. در این مورد می‌توانید به نقشه‌ی راه ما مراجعه کنید.

نکته:

React.lazy() و <React.Suspense> هنوز توسط ReactDOMServer پشتیبانی نمی‌شوند. این یک محدودیت شناخته شده است که در آینده برطرف خواهد شد.