Обычно вы определяете компонент React как обычный класс JavaScript:

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 классов ES6 аналогичен createReactClass() некоторым исключениям.

Объявление props по умолчанию

С функциями и классами ES6 defaultProps определяется как свойство самого компонента:

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

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

С помощью функции передаваемого объекта createReactClass() необходимо определить getDefaultProps():

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

  // ...

});

Установка начального состояния

В классах 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};
  },
  // ...
});

Автоматическое связывание

В компонентах React, объявленных как классы ES6, методы следуют той же семантике, что и обычные классы 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>
    );
  }
});

Это означает, что для написания классов ES6 имеется немного более шаблонный код для обработчиков событий, но потенциал роста в некоторых приложениях несколько лучше.

Если код шаблона слишком непривлекателен для вас, вы можете включить экспериментальное предложение экспериментального свойства класса с 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. Поэтому, если вы используете React с классами ES6, поддержка mixins не поддерживается.

Мы также обнаружили множество проблем в кодовых файлах с использованием mixins и не рекомендуем использовать их в новом коде .

Иногда очень разные компоненты могут использовать некоторые общие функции. Иногда их называют сквозными проблемами .createReactClass позволяет использовать для этого устаревшую mixins систему.

Одним из распространенных вариантов использования является компонент, который хочет обновить себя на временной интервал. Он прост в использовании setInterval(), но важно отменить свой интервал, когда он вам больше не нужен, чтобы сэкономить память. React предоставляет методы жизненного цикла, которые позволяют вам знать, когда компонент будет создан или уничтожен. Давайте создадим простой mixin, который использует эти методы, чтобы обеспечить легкую 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')
);

Если компонент использует несколько микшинов, а несколько миксинов определяют один и тот же метод жизненного цикла (т.е. Несколько миксинов хотят выполнить некоторую очистку при уничтожении компонента), все методы жизненного цикла гарантированно будут вызваны. Были указаны методы, определенные для mixins, выполняемые в бинарниках заказа, после чего следует вызов метода для компонента.