ری‌اکت بدون ES6

به طور معمول شما کامپوننت React را به صورت یک class جاوا اسکریپت ساده تعریف می‌کنید:

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

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

var createReactClass = require('create-react-class');
var Greeting = createReactClass({
  render: function() {
    return <h1>Hello, {this.props.name}</h1>;
  }
});

API مربوط به class های ES6 خیلی شبیه createReactClass() است ولی چند تفاوت دارد.

اعلام prop های پیش‌فرض

با توابع و class های ES6، به عنوان مشخصه‌ای از خود کامپوننت defaultProps تعریف شده است:

class Greeting extends React.Component {
  // ...
}

Greeting.defaultProps = {
  name: 'Mary'
};

با createReactClass()، شما نیاز به تعریف getDefaultProps() به عنوان یک تابع روی آبجکت منتقل شده دارید:

var Greeting = createReactClass({
  getDefaultProps: function() {
    return {
      name: 'Mary'
    };
  },

  // ...

});

تنظیم حالت اولیه

در class های ES6، شما می‌توانید حالت اولیه را به وسیلۀ اختصاص دادن this.state در سازنده، تعریف کنید:

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  // ...
}

با createReactClass()، شما باید یک متد getInitialState مجزا که حالت اولیه را برمی‌گرداند، آماده کنید:

var Counter = createReactClass({
  getInitialState: function() {
    return {count: this.props.initialCount};
  },
  // ...
});

Autobinding

در کامپوننت‌های React که به صورت class های ES6 معرفی شده‌اند، متدها مفاهیم مشابهی را مانند class های ES6 دنبال می‌کنند. این یعنی آنها به طور خودکار this را مقید نمی‌کنند. شما باید به طور صریح در سازنده از .bind(this) استفاده کنید:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
    // This line is important!
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    alert(this.state.message);
  }

  render() {
    // Because `this.handleClick` is bound, we can use it as an event handler.
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}

با createReactClass()، نیازی به انجام این کار نیست زیرا تمام متدها را مقید می‌کند:

var SayHello = createReactClass({
  getInitialState: function() {
    return {message: 'Hello!'};
  },

  handleClick: function() {
    alert(this.state.message);
  },

  render: function() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
});

این یعنی نوشتن class های ES6 کمی کد boilerplate بیشتری برای کنترل کننده‌های رویدادها به همراه دارد، اما مزیت آن عملکرد بهتر در برنامه‌های بزرگ است.

اگر کد boilerplate برایتان جذاب نیست، می‌توانید درخواست سینتکس آزمایشی Class Properties با Babel را فعال کنید:

class SayHello extends React.Component {
  constructor(props) {
    super(props);
    this.state = {message: 'Hello!'};
  }
  // WARNING: this syntax is experimental!
  // Using an arrow here binds the method:
  handleClick = () => {
    alert(this.state.message);
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        Say hello
      </button>
    );
  }
}

دقت کنید که سینتکس بالا آزمایشی بوده و ممکن است تغییر کند و یا درخواست شما نتواند آن را به زبان بیاورد.

اگر دنبال راه مطمئنی هستید، چند گزینه دارید:

  • متدها را در سازنده مقید کنید
  • از توابع پیکانی استفاده کنید، مانند onClick={(e) => this.handleClick(e)}
  • از createReactClass استفاده کنید

مخلوط‌ها (Mixins)

نکته: ES6 بدون پشتیبانی mixin راه‌اندازی شده است. بنابراین، هیچ پشتبانی از مخلوط‌ها هنگامی که شما از class های ES6 در React استفاده می‌کنید وجود ندارد. همچنین ما مشکلات زیادی هنگام استفاده از مخلوط‌ها پیدا کرده‌ایم، و توصیه می‌کنیم در کدهای جدید از آنها استفاده نکنید. این قسمت فقط برای مرجع و کامل بودن بحث آورده شده است.

گاهی اوقات کامپوننت‌هایی که تفاوت زیادی با هم دارند، عملکردهای مشترکی نشان می‌دهند. به اینها گاهی cross-cutting concerns گفته می‌شود. createReactClass به شما اجازه می‌دهد از یک میراث سیستم مخلوط‌ها برای آن استفاده کنید.

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

var SetIntervalMixin = {
  componentWillMount: function() {
    this.intervals = [];
  },
  setInterval: function() {
    this.intervals.push(setInterval.apply(null, arguments));
  },
  componentWillUnmount: function() {
    this.intervals.forEach(clearInterval);
  }
};

var createReactClass = require('create-react-class');

var TickTock = createReactClass({
  mixins: [SetIntervalMixin], // Use the mixin
  getInitialState: function() {
    return {seconds: 0};
  },
  componentDidMount: function() {
    this.setInterval(this.tick, 1000); // Call a method on the mixin
  },
  tick: function() {
    this.setState({seconds: this.state.seconds + 1});
  },
  render: function() {
    return (
      <p>
        React has been running for {this.state.seconds} seconds.
      </p>
    );
  }
});

ReactDOM.render(
  <TickTock />,
  document.getElementById('example')
);

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

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