نگاهی به سرگذشت انواع کامپوننت ها در ری اکت
زمان مطالعه:8 دقیقه

نگاهی به سرگذشت انواع کامپوننت ها در ری اکت

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

React createClass Components

همه چیز با React createClass Components شروع شد. متد createClass توسعه دهندگان را قادر به ایجاد یک کلاس کامپوننت بدون استفاده از سینتکس کلاس های جاوااسکریپت میکرد و این متد تنها راه ایجاد یک کلاس کامپوننت بود و دلیلش هم این بود که در اون موقع و قبل از ورژن ES6 یعنی در ES5 هیچ سینتکسی برای ایجاد کلاس موجود نبود.

var App = React.createClass({
  getInitialState: function() {
    return {
      value: '',
    };
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React "createClass" Component!</h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

متد createClass یک آبجکت به عنوان ورودی میگیره و این آبجکت هم به یکسری کلید ها جهت ایجاد کلاس کامپوننت نیاز داره. کلید getInitialState که در واقع state ما هست و کلید اجباری render هم که به کار میره تا jsx را بنویسیم. متد های اضافی دیگه هم مثله onChange وجود دارن تا بتونیم فانکشن های بیشتری را به کامپوننت اضافه کنیم.

همچنین متدهای LifeCycle هم در این کامپوننت ها وجود داشتن تا به عنوان مثال بتونیم با هربار رندر مجدد کامپوننت قطعه کدی که مدنظر داریم را اجرا کنیم.

ar App = React.createClass({
  getInitialState: function() {
    return {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  },

  componentDidUpdate: function() {
    localStorage.setItem('myValueInLocalStorage', this.state.value);
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React "createClass" Component!</h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

مثلا در کد بالا با هربار تغییر مقدار input و state اون مقدار را توی localStorage ذخیره میکنیم تا بعد از رفرش شدن صفحه هم مقادیر تایپ شده قبلی وجود داشته باشند.

نکته:به خاطر داشته باشید که متد createClass دیگه در ری اکت وجود نداره و اگر میخواهید ازش استفاده کنید نیازه اونرو با دستور npm install create-react-class نصب و به پروژتون اضافه کنید.

در کل هم بهتره از createClass استفاده نکنید، چراکه این متد منسوخ شده.

React Mixins

React Mixin به عنوان اولین pattern پیشرفته برای قابل استفاده مجدد شدن کامپوننت ها معرفی شد تا این امکان رو به توسعه دهنده ها بده که تا حد خوبی منطق کد خودشون رو از کامپوننت ها جدا کنند.

var localStorageMixin = {
  getInitialState: function() {
    return {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  },

  setLocalStorage: function(value) {
    localStorage.setItem('myValueInLocalStorage', value);
  },
};

var App = React.createClass({
  mixins: [localStorageMixin],

  componentDidUpdate: function() {
    this.setLocalStorage(this.state.value);
  },

  onChange: function(event) {
    this.setState({ value: event.target.value });
  },

  render: function() {
    return (
      <div>
        <h1>Hello React "createClass" Component with Mixin!</h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  },
});

در کد بالا یک Mixin ایجاد کردیم که یک state و یک متد برای setState کردن را به کامپوننت مدنظر ما اضافه میکنه. state ما حاوی مقداری هست که از localStorage خوانده میشه و setState ما هم مقدار جدیدی را در localStorage مینویسه.

همچنین برای منعطف تر و داینامیک تر کردن Mixin میتونیم اونرو تبدیل به فانکشنی کنیم که یک آبجکت را بر میگردونه:

function getLocalStorageMixin(localStorageKey) {
  return {
    getInitialState: function() {
      return { value: localStorage.getItem(localStorageKey) || '' };
    },

    setLocalStorage: function(value) {
      localStorage.setItem(localStorageKey, value);
    },
  };
}

var App = React.createClass({
  mixins: [getLocalStorageMixin('myValueInLocalStorage')],

  ...
});

هرچند که عمر Mixin ها هم به سر آمده و دیگه از اونها توی اپلیکیشن های مدرن استفاده نمیشه.

React Class Components

کلاس کامپوننت ها همراه با ورژن ES6 جاوااسکریپت معرفی شدن و از اینرو گاهی اوقات اونهارو React ES6 class components هم مینامیم. متد createClass پس از معرفی کلاس کامپوننت ها از میان برداشته شد و دیگه احتیاجی نیست برای ایجاد یک کلاس کامپوننت از متد یاد شده استفاده کرد.

کلاس کامپوننت های ری اکتی همراه با یسکری متد ها میاد، متدهایی مثل class constructor که برای ایجاد state و یا bind کردن متدها استفاده میشه و یا render که جهت خروجی کار و نمایش jsx بکار میره.

نکته: برای bind شدن خودکار متد ها میتونیم از arrow function ها در کلاس کامپوننت هامون استفاده کنیم.

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

    this.state = {
      value: '',
    };
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>Hello React ES6 Class Component!</h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

همچنین در کلاس کامپوننت ها ما یسکری متد lifeCycle برای mounting, updating و unmounting داریم که میتونیم از اونها برای side-effect ها استفاده کنیم.

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

    this.state = {
      value: localStorage.getItem('myValueInLocalStorage') || '',
    };
  }

  componentDidUpdate() {
    localStorage.setItem('myValueInLocalStorage', this.state.value);
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>Hello React ES6 Class Component!</h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

لازم به ذکر هست که کلاس کامپوننت ها همچنان در اپلیکیشن های مدرن هم استفاده میشن، هرچند کمی کمرنگ تر، اما همچنان پابرجا هستند و استفاده های خاص خودشون را دارند.

React Higher-Order Components

React Higher-Order Component  یا (HOCs) یک راه جایگزین و محبوب برای Mixin ها هستند تا ما بتونیم بوسیله اونها منطق های قابل استفاده مجدد خودمون را بین کامپوننت ها رد و بدل کنیم.

به زبانی ساده تر، Higher-Order Component را به کامپوننتی میگن که به عنوان ورودی یک کامپوننت دریافت میکنه و بعد اون کامپوننت را به عنوان خروجی و با عملکردی بیشتر تحویل میده.

به عنوان مثال نمونه کدی که قبل تر در کلاس کامپوننت نوشتیم تا مقدار input را در localStorage بنویسه و بعد درصورت رفرش شدن به عنوان مقدار اولیه state داشته بخونتش را بیایید با سینتکس React Higher-Order Component ببینیم:

const withLocalStorage = localStorageKey => Component =>
  class WithLocalStorage extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        [localStorageKey]: localStorage.getItem(localStorageKey),
      };
    }

    setLocalStorage = value => {
      localStorage.setItem(localStorageKey, value);
    };

    render() {
      return (
        <Component
          {...this.state}
          {...this.props}
          setLocalStorage={this.setLocalStorage}
        />
      );
    }
  };

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

    this.state = { value: this.props['myValueInLocalStorage'] || '' };
  }

  componentDidUpdate() {
    this.props.setLocalStorage(this.state.value);
  }

  onChange = event => {
    this.setState({ value: event.target.value });
  };

  render() {
    return (
      <div>
        <h1>
          Hello React ES6 Class Component with Higher-Order Component!
        </h1>

        <input
          value={this.state.value}
          type="text"
          onChange={this.onChange}
        />

        <p>{this.state.value}</p>
      </div>
    );
  }
}

const AppWithLocalStorage = withLocalStorage('myValueInLocalStorage')(App);

از React Higher-Order Component ها هم همچنان بصورت منظم در اپلیکیشن های مدرن استفاده میشه.

React Function Components

state و متدهای lifeCycle در اوایل راه در فانکشنال کامپوننت ها وجود نداشتند و از اینرو این کامپوننت هارو Functional Stateless Components مینامیدند. اما کار به همینجا ختم نشد و کمی بعد سیستم هوک های ری اکت معرفی شدن و این هوک ها به فانکشنال کامپوننت ها روحی دوباره دادن.

این هوک ها state و lifeCycle هارو مجددا به این نوع از کامپوننت ها اضافه کردند و علاوه بر این دست توسعه دهنده را برای ایجاد هوک های شخصی هم باز گذاشتن.

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

const App = () => {
  const [value, setValue] = React.useState('');

  React.useEffect(() => {
    localStorage.setItem('myValueInLocalStorage', value);
  }, [value]);

  const onChange = event => setValue(event.target.value);

  return (
    <div>
      <h1>Hello React Function Component!</h1>

      <input value={value} type="text" onChange={onChange} />

      <p>{value}</p>
    </div>
  );
};

در کد بالا از هوک useState برای ذخیره مقدار input استفاده میکنیم و همچنین از هوک useEffect جهت هندل کردن side-effect و نوشتن مقدار جدید با هربار تغییر مقدار input استفاده میکنیم.

همانطور که در کدبالا مشاهده میکنید، ما state خودمون را به این شکل [value] به عنوان dependency به هوک useEffect دادیم تا کار آپدیت کردن را برای ما انجام بده و به این شکل به این هوک گفتیم که با هربار تغییر value بیا کدی که درونت نوشتیم را مجدد اجرا کن و مقدار جدید را در localStorage ذخیره کن.

همچنین میتونیم کاری که در بالا انجام میدیم یعنی state و useEffect خودمون را به یک custom hook ( هوک شخصی ) منتقل کنیم و به این شکل اولین هوک شخصی خودمون را ایجاد کنیم:

const useStateWithLocalStorage = localStorageKey => {
  const [value, setValue] = React.useState(
    localStorage.getItem(localStorageKey) || '',
  );

  React.useEffect(() => {
    localStorage.setItem(localStorageKey, value);
  }, [value]);

  return [value, setValue];
};

const App = () => {
  const [value, setValue] = useStateWithLocalStorage(
    'myValueInLocalStorage',
  );

  const onChange = event => setValue(event.target.value);

  return (
    <div>
      <h1>Hello React Function Component!</h1>

      <input value={value} type="text" onChange={onChange} />

      <p>{value}</p>
    </div>
  );
};

و با این کار میتونیم منطق کد خودمون را بوسیله یک custom hook بین تمامی کامپوننت هامون به اشتراک بگذاریم و کدی قابل استفاده مجدد بنویسیم. سیستم هوک های ری اکت انعطاف پذیری و قدرت خیلی زیادی را به اپلیکیشن های ری اکتی اضافه کردند و بطور کلی ری اکت را متحول کردن و از اینرو ما معتقدیم که استفاده از کلاس کامپوننت ها یروزی بطور کامل کنار خواهد رفت ( هرچند که همین الان هم به شدت کمرنگ شده )

react components

#

components

#

https://vaspar.io/blog/react-component-types

اشتراک گذاری:

نظرات

500

/

0