کامپوننت های خالص در ری اکت

05 فروردین 1398
درسنامه درس 11 از سری آموزش react (ری اکت)
React-stateless

ری اکت روش های مختلفی را برای ساخت یک کامپوننت پیشنهاد می کند. در این درس درباره آخرین روش ساخت یک کامپوننت با استفاده از کامپوننت های خالص بدون وضعیت (stateless) صحبت می کنیم.

در درس های قبلی روش های مختلف ساخت یک کامپوننت در ری اکت را بررسی کردیم. روشی که در این درس قصد داریم به آن بپردازیم، ساخت کامپوننت های بدون وضعیت در ری اکت است.

تا به اینجای آموزش ما با استفاده از متدهای React.Component و ()React.createClass اقدام به ساخت کامپوننت ها می کردیم. ری اکت به منظور کارایی و سادگی بیشتر، امکان ساخت کامپوننت های بدون وضعیت با استفاده از یک تابع معمولی جاوا اسکریپت را فراهم کرده است.

یک کامپوننت خالص می تواند جایگزین یک کامپوننتی شود که تنها یک متد render دارد.

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

کامپوننت های خالص آسانترین و سریع ترین کامپوننت هایی هستند که ما می توانیم بنویسیم. قبل از اینکه بگوییم چرا این کامپوننت ها بهتر از بقیه هستند، اجازه بدهید یک کامپوننت از این نوع را ایجاد کنیم:

// The simplest one
const HelloWorld = () => (<div>Hello world</div>);

// A Notification component
const Notification = (props) => {
  const {level, message} = props;
  const classNames = ['alert', 'alert-' + level]
  return (
    <div className={classNames}>
      {message}
    </div>
  )
};

// In ES5
var ListItem = function(props) {
  var handleClick = function(event) {
    props.onClick(event);
  };

  return (
    <div className="list">
      <a
        href="#"
        onClick={handleClick}>
          {props.children}
      </a>
    </div>
  )
}

همان طور که می بینید این کامپوننت ها صرفا یک تابع هستند، بنابراین به راحتی توسط جاوا اسکریپت می شود آنها را تست کرد.

props های مشابه، خروجی های DOM مجازی مشابهی هم دارند.

در ری اکت، کامپوننت های تابعی توسط یک آرگومان به نام props فراخوانی می شوند (مشابه کلاس سازنده در React.Component) و این propsها با context کامپوننت جاری فراخوانی می شود.

برای مثال، فرض کنید که می خواهیم کامپوننت Timer را با استفاده از کامپوننت های تابعی بازنویسی کنیم و به کاربران این امکان را بدهیم تا بتوانند استایل ساعت شان را بطور دینامیک مشخص کنند. (مثلاً زمان 12 یا 24 ساعته، جداکننده های مختلف، امکان عدم نمایش ثانیه و ...)

حال می خواهیم کامپوننت های clock را به چند کامپوننت دیگر تقسیم کنیم. بنابراین هر بلوک زمانی را در یک کامپوننت مستقل ایجاد خواهیم کرد. مطابق زیر:

const Hour    = (props) => {
  let {hours} = props;
  if (hours === 0) { hours = 12; }
  if (props.twelveHours) { hours -= 12; }
  return (<span>{hours}</span>)
}
const Minute  = ({minutes}) => (<span>{minutes<10 && '0'}{minutes}</span>)
const Second  = ({seconds}) => (<span>{seconds<10 && '0'}{seconds}</span>)
const Separator = ({separator}) => (<span>{separator || ':'}</span>)
const Ampm = ({hours}) => (<span>{hours >= 12 ? 'pm' : 'am'}</span>)

حال می توانیم به جای استفاده از کامپوننت Clock از این کامپوننت های مجزا استفاده کنیم:

<div>Minute: <Minute minutes={12} /></div>
<div>Second: <Second seconds={51} /></div>

کامپوننت clock را تغییر می دهیم تا بتواند یک رشته متنی را دریافت کند، و توسط این رشته بتوانیم تنها آن زمان های دلخواه (ساعت، دقیقه و ... ) را نمایش دهیم. چندین روش برای انجام اینکار وجود دارد، مثلاً اجرای کد در داخل کامپوننت clock و یا ایجاد یک کامپوننت بدون وضعیت دیگر که یک رشته متنی را دریافت کند.

const Formatter = (props) => {
  let children = props.format.split('').map((e, idx) => {
    if (e === 'h') {
      return <Hour key={idx} {...props} />
    } else if (e === 'm') {
      return <Minute key={idx} {...props} />
    } else if (e === 's') {
      return <Second key={idx} {...props} />
    } else if (e === 'p') {
      return <Ampm key={idx} {...props} />
    } else if (e === ' ') {
      return <span key={idx}> </span>;
    } else {
      return <Separator key={idx} {...props} />
    }
  });

  return <span>{children}</span>;
}

کد بالا به دلیل استفاده از key و {… props} ظاهر مناسبی ندارد. ری اکت تعدادی helper برای کار با کامپوننت های فرزند و مدیریت key منحصر به فرد مربوط به هر عنصر فرزند از طریق آبجکت React.Children، برای ما فراهم کرده است.

تابع render() در کامپوننت clock به دلیل استفاده از کامپوننت formatter خیلی ساده تر شده است.

class Clock extends React.Component {
  state = { currentTime: new Date() }
  componentDidMount() {
    this.setState({
      currentTime: new Date()
    }, this.updateTime);
  }
  componentWillUnmount() {
    if (this.timerId) {
      clearTimeout(this.timerId)
    }
  }

  updateTime = e => {
    this.timerId = setTimeout(() => {
      this.setState({
        currentTime: new Date()
      }, this.updateTime);
    })
  }

  render() {
    const { currentTime } = this.state
    const hour = currentTime.getHours();
    const minute = currentTime.getMinutes();
    const second = currentTime.getSeconds();

    return (
      <div className='clock'>
        <Formatter
          {...this.props}
          state={this.state}
          hours={hour}
          minutes={minute}
          seconds={second}
        />
      </div>
    )
  }
}

حال نه تنها کامپوننت clockساده تر شد، بلکه براحتی می شود از این کامپوننت تست گرفت. همچنین به ما کمک می کند تا بتوانیم به راحتی به فریمورک های مدیریت وضعیت مثل Flux/Redux نرم افزارهای خود را طراحی کنیم.

مزایا و معایب کامپوننت های تابعی

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

  • می توانیم با برداشتن اجزای سنگین مثل سازنده ها، stateها، چرخه حیات و ...، کامپوننت سبک تری داشته باشیم
  • نیازی به استفاده از کلمه کلیدی this نداریم
  • کامپوننت های نمایشی (یا کامپوننت های dump) به رابط کاربری بیشتر از منطق تاکید دارند (نیازی به کار با state در کامپوننت ها نیست)
  • ما را ترغیب می کند تا کامپوننت های کوچک تری ایجاد کنیم
  • کدنویسی های نامرتب را برجسته می کند (به منظور راحت شدن عملیات refactoring)
  • سرعت بالاتری دارند
  • به آسانی می شود از این کامپوننت استفاده مجدد کرد

احتمالاً با خود می گویید، پس چرا نباید همیشه از کامپوننت های تابعی استفاده کنم؟

در زیر تعدادی از معایب کامپوننت های تابعی را آورده ایم:

  • هیچ متد چرخه حیاتی ندارند.
  • قابلیت های محدودتری دارند.
  • کلمه کلیدی this ندارند.

در کل استفاده از کامپوننت های تابعی نسبت به کامپوننت های سنگین تر مثل React.Component توصیه می شود.

به این ترتیب تا به امروز سه روش ساخت کامپوننت در ری اکت را بررسی کردیم.

در درس بعدی به روش ساخت برنامه های ری اکت توسط create-react-app که یک ابزار مدیریت پکیج بوده و توسط تیم ری اکت توسعه پیدا کرده است، می پردازیم.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش react (ری اکت) توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (1 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

Hosein
28 فروردین 1401
مزایا نیازی به استفاده از کلمه کلیدی this نداریم معایب کلمه کلیدی this ندارند. !!!!

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.