نگاهی به امکانات تازه ری اکت 16.6.0

ری اکت نسخه 16.6.0 اومد و یه سری امکانات جدید داره که نگاهی میکنیم به این امکانات:




Memo

برای Class Component ها ما Pure Component رو داشتیم. Memo برای function component هاست .Pure Component ها نوع خاصی از Component هاست که state و prop رو بررسی میکنه و اگه این 2 تغییری نداشتن از رندر دوباره Component جلو گیری میکنه که باعث بهبود performance میشه.

از اونجایی که بررسی prop و state ها در این نوع کامپوننت ها سطحی(shallow) هست و deep نیست اگر ابجکت state/prop شما پیچیده باشه Pure پیشنهاد نمیشه و بهتره که خودمون از متد shouldComponentUpdate استفاده کنیم


استفاده از Memo راحته کافیه function component خودمون رو به Memo بدیم (Wrap کنیم) بدین صورت:

const MyComponent = React.memo(function MyComponent(props) {
    /* only rerenders if props change */
  });



Lazy/Suspense

بهترین راه برای code-splitting استفاده از dynamic import هست. React Lazy به شما اجازه میده خیلی راحتتر این مورد رو هندل کنین و با کمک lazy بتونین با dynamic import ها همانند یک کامپوننت رفتار کنیم. بدین شکل:

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent')); 

بعد ازین شما از OtherComponent میتونین مثل یک کامپوننت معمولی استفاده کنین و فقط وقتی رندر میشه که import مون کامل شد.

تا زمانی که OtherComponent لود و رندر نشده باید یه fallback یی داشته باشیم. برای این کار از یه Component به نام Suspense استفاده میکنیم که lazy component هارو به عنوان children و fallback یی که یک React Component یا المنت هست رو به عنوان prop میگیره و تا زمانی که lazy component هامون لود نشده اون رو نمایش میدیم.

بدین شکل:

 <Suspense fallback={<div>Loading...</div>}>
    <OtherComponent />
 </Suspense>



static contextType

در ری اکت 16.3 ری اکت context api رو معرفی کرد. که ما در مقاله زیر به طور کامل معرفی اش کردیم.

https://virgool.io/JavaScript8/%D8%B1%DB%8C-%D8%A7%DA%A9%D8%AA-%D8%A8%D8%A7%D8%AD%D8%A7%D9%84%D9%87-%D8%A8%DB%8C%D8%A7%DB%8C%D9%86-%D8%A8%D8%A7%D8%AD%D8%A7%D9%84-%D8%AA%D8%B1%D8%B4-%DA%A9%D9%86%DB%8C%D9%85-%DB%B1-pycysgrv64wi

ولی استفاده ازونا در class component ها یه مقدار مشکل بود برای همین در این نسخه شما میتونین به class تون به صورت static یه contextType رو معرفی کنین و ازین به بعد از طریق this.context به مقدار اون context دسترسی داشته باشین.

توجه داشته باشین که فقط به یه context بدین شکل میتونین دسترسی بهش داشته باشین.

شیوه کار هم بدین شکل هست :

const MyContext = React.createContext();

و سپس در کلاستون :

class MyClass extends React.Component {
    static contextType = MyContext;
    componentDidMount() {
      let value = this.context;
      /* perform a side-effect at mount using the value of MyContext */
    }
    componentDidUpdate() {
      let value = this.context;
      /* ... */
    }
    componentWillUnmount() {
      let value = this.context;
      /* ... */
    }
    render() {
      let value = this.context;
      /* render something based on the value of MyContext */
    }
}




static getDerivedStateFromError()

در ری اکت 16 مفهوم Error Boundaries برای هندل کردن خطا ها معرفی شد و ما متد componentDidCatch ئه lifecycle رو داریم که با کمکش میتونیم کارای لازم مثل log کردن رو انجام بدیم . ولی مشکلش اینجا بود که ری اکت وقتی به خطا برخورد میکنه عوض رندر component ابتدا null رو در جایی که خطا رخ داده رندر میکنه و اگر یه parent ئی داشته باشیم که ref داشته باشه اون خالی میشه و ممکنه به مشکل بخوریم. همچنین وقتی به خطا خوردیم اون روش مشکلی رو وقتی server rendering بکنیم حل نمیکنه ازونجایی که متد Did ئه lifecycle اجرا نمیشه. برای حل این مشکل این امکان جدید اضافه شده تا مشکلات بالا رو حل کنه.

این متد lifecycle جدید وقتی یکی فرزندان component دچار خطا بشه صدا زده میشه تا fallback UI ئی داشته باشیم. شما در این متد باید object ئی برگردونین state رو بروزرسانی کنین.

پس فرق این ۲ متد در اینه که برای fallback UI از getDerivedStateFromError و برای لاگ کردن از componentDidCatch استفاده میکنیم.

روش استفاده اش هم بدین شکل هست:

class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false };
   }
  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true };
  }
  render() {
        if (this.state.hasError) {
            // You can render any custom fallback UI
            return <h1>Something went wrong.</h1>;
       }
        return this.props.children; 
    }
}


۲ قابلیت Lazy و getDerivedStateFromError فعلا برای server-rendering در دسترس نیستند و بزودی در release آینده در دسترس خواهند بود.