Strict Mode در React

StrictMode یک ابزار جهت مشخص کردن (هایلایت) مشکلات بالقوه در یک برنامه است. StrictMode مانند Fragment هیچ رابط کاربری آشکاری را رندر نمی‌کند بلکه کنترل‌های اضافی و اخطاراتی برای نسل خود فعال می‌کند.

نکته: کنترل‌های Strict mode فقط در حالت برنامه نویسی اجرا می‌شوند؛ آنها تاثیری روی محصول تولیدی ندارند.

شما می‌توانید Strict mode را برای هر بخش از برنامه‌تان فعال کنید. برای مثال:

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

در مثال بالا، کنترل‌های Strict mode برای کامپوننت‌های Header و Footer اجرا نشده و برای ComponentOne و ComponentTwo و نسل‌هایشان اجرا می‌شود.

در موارد زیر، StrictMode به ما کمک می‌کند:

  • تشخیص کامپوننت‌هایی که چرخۀ زندگی ناایمن دارند
  • اخطار در مورد استفادۀ میراث رشتۀ ref API
  • اخطار در مورد استفاده از findDOMNode منسوخ
  • تشخیص اثرات جانبی غیرمنتظره
  • تشخیص زمینۀ میراث API

عملکردهای بیشتری در نسخه‌های آیندۀ React اضافه خواهد شد.

تشخیص کامپوننت‌هایی که چرخۀ زندگی ناایمن دارند

برخی میراث متدهای چرخۀ زندگی برای استفاده در برنامه‌های async ری اکت ناایمن هستند. اگر برنامه شما از کتابخانه‌های جانبی استفاده می‌کند، تشخیص این که این چرخه‌های زندگی مورد استفاده قرار نمی‌گیرند سخت خواهد شد. خوشبختانه strict mode در این مورد می‌تواند به ما کمک کند.

وقتی strict mode فعال باشد، React یک لیست از کامپوننت‌های class که از چرخه‌های زندگی ناایمن استفاده می‌کنند، گردآوری می‌کند و پیغام اخطاری حاوی اطلاعاتی پیرامون این کامپوننت‌ها ارسال می‌کند، مانند این:

strict-mode-unsafe-lifecycles-warning

با توجه به اشکالات تشخیص داده شده توسط strict mode، اکنون استفاده از مزیت‌های async در نسخه‌های آیندۀ React برایتان آسان‌تر خواهد بود.

اخطار در مورد استفادۀ میراث رشتۀ ref API

قبلا React دو روش برای مدیریت refها فراهم کرده بود: استفادۀ میراث رشتۀ ref API و فراخوانی API. هرچند میراث رشتۀ ref API از بین این دو روش راحت‌تری بود اما معایبی داشت که باعث می‌شد توصیه ما روش فراخوانی API باشد.

نسخۀ ۱۶.۳ ری‌اکت یک گزینۀ سوم اضافه کرد که راحتی روش رشتۀ 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();
  }
}

از آن جایی که refهای آبجکت تا حد زیادی به عنوان جایگزینی برای refهای رشته‌ای اضافه شد، اکنون strict mode در مورد استفاده از refهای رشته‌ای هشدار خواهد داد.

نکته: refهای فراخوانی شده همچنان با وجود اضافه شده createRef API جدید، تحت پشتیبانی هستند. شما نیاز به جایگزین کردن refهای فراخوانی شده در کامپوننت‌های خود ندارید. آنها کمی انعطاف‌پذیرتر هستند و لذا به عنوان یک قابلیت پیشرفته باقی خواهند ماند.

در این قسمت می‌توانید در مورد createRef API بیشتر بدانید.

اخطار در مورد استفاده از findDOMNode منسوخ

قبلا React از findDOMNode جهت جستجوی درخت با یک DOM node حاوی یک شیء class داده شده، پشتیبانی می‌کرد. به طور معمول شما نیازی به آن ندارید زیرا می‌توانید یک ref را به طور مستقیم به DOM node وصل کنید.

همچنین findDOMNode می‌تواند در کامپوننت‌های class مورد استفاده قرار گیرد اما این کار با اجازه دادن به والد جهت تقاضای children خاصی که رندر شده است، سطوح انتزاعی را خراب می‌کرد. این موضوع در جایی که شما به علت اینکه شاید یک والد به DOM node خود برسد، نمی‌توانید جزئیات پیاده سازی کامپوننت را تغییر دهید، خطر بازسازی را ایجاد می‌کند. findDOMNode فقط اولین child را برمی‌گرداند اما با استفاده از Fragment ها، کامپوننت‌ها خواهند توانست چندین DOM node را رندر کنند. findDOMNode یک خوانندۀ API یک زمانی است. فقط هنگامی به شما جواب می‌دهد از آن سوال کنید. اگر یک کامپوننت child یک node متفاوت را رندر کند، راهی برای مدیریت این تغییر نخواهد بود. بنابراین findDOMNode فقط زمانی کار می‌کرد که کامپوننت‌ها همیشه یک DOM node تنها را که هیچ وقت تغییر نمی‌کند، برگردانند.

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

شما می‌توانید یک بسته بندی کنندۀ DOM node را نیز به کامپوننت خود اضافه کنید و یک ref را به طور مستقیم به آن متصل کنید.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.wrapper = React.createRef();
  }
  render() {
    return <div ref={this.wrapper}>{this.props.children}</div>;
  }
}

تشخیص اثرات جانبی غیرمنتظره

از نظر مفهومی React در دو فاز کار می‌کند:

  • فاز render که تعیین می‌کند چه تغییراتی باید صورت پذیرد. در این فاز React رندر را فراخوانی کرده و سپس نتایج را با رندر قبلی مقایسه می‌کند.
  • فاز commit که React هر تغییری را اعمال می‌کند. (در مورد DOM این فاز هنگامی است که ری اکت DOM node ها را قرار داده یا آپدیت و یا حذف می‌کند) همچنین React در این فاز است که چرخه‌های زندگی مانند componentDidMount و componentDidUpdateduring را فراخوانی می‌کند.

فاز commit معمولا خیلی سریع است اما رندر کردن ممکن است کند باشد. به همین دلیل، مود async (که هنوز به طور پیش‌فرض فعال نشده است) قسمت‌های رندر را به قطعات مختلفی تقسیم می‌‌کند و کار را متوقف و از سر می‌گیرد تا از مسدود شدن مرورگر جلوگیری کند. این یعنی ممکن است React بیش از یک بار چرخه‌های زندگی فاز رندر را قبل از commit فراخوانی کند و حتی ممکن است بدون commit کردن، آنها را فراخوانی کند.

چرخه‌های زندگی فاز render شامل متدهای کامپوننت class زیر می‌شود:

  • constructor
  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • تابع آپدیت کنندۀ setstate (آرگومان اول)

 

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

Strict mode نمی‌تواند به طور خودکار این اثرات جانبی را برایتان پیدا کند اما با کمی تعینی کردن آنها به شما کمک می‌کند آنها را تشخیص دهید. این موضوع با دو طرفه کردن (double-invoked) عمدی متدهای زیر انجام می‌شود:

  • متد constructor کامپوننت class
  • متد render
  • تابع آپدیت کنندۀ setstate (آرگومان اول)
  • چرخۀ زندگی استاتیک getDerivedStateFromProps

نکته: این فقط در قسمت برنامه نویسی فعال است. چرخه‌های زندگی در قسمت تولید دو طرفه نمی‌شوند.

برای مثال، کد زیر را در نظر بگیرید:

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

    SharedApplicationState.recordEvent('ExampleComponent');
  }
}

در نگاه اول، ممکن است مشکلی در این کد دیده نشود. اما اگر SharedApplicationState.recordEvent به صورت تکرار شونده (idempotent) نباشد، معرفی کردن چند بارۀ این کامپوننت می‌تواند منجر به نامعتبر شدن حالت برنامه شود. این نوع از مشکلات نامحسوس و ریز ممکن است در رمان برنامه نویسی آشکار نشود و یا نادیده گرفته شود.

با دو طرفه کردن عمدی متدهایی مانند constructor توسط strict mode، تشخیص الگوهایی ماندد این‌ها آسان‌تر خواهد شد.

تشخیص زمینۀ میراث API

زمینۀ میراث API مستعد ایجاد ارور است و در نسخه‌های آینده حذف خواهد شد. در نسخۀ ۱۶.x کار کرده اما در strict mode پیغام هشدار زیر را نشان می‌دهد:

warn-legacy-context-in-strict-mode

جهت راهنمایی بیشتر برای انتقال به نسخه جدید، داکیومنت Context را مطالعه نمایید.

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 5٫00 out of 5)
Loading...

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

counter customizable free hit