Ответ 1
Я считаю, что это вопрос личных предпочтений. Транспортированный вывод одинаков с точки зрения семантики.
Согласно этой документации для babel, правильный способ использования ES6 + с React - это исходные компоненты вроде этого:
class Video extends React.Component {
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
}
state = {
loopsRemaining: this.props.maxLoops,
}
}
Но некоторые официальные примеры, такие как Dan Abramov собственный React DnD модуль, использует ES6 +, но все еще определяет состояние внутри конструктора:
constructor(props) {
super(props);
this.moveCard = this.moveCard.bind(this);
this.state = {
// state stuff
}
}
Теперь Дэн Абрамов, будучи значительным вкладчиком в Реакт, вероятно, знает, что он может определить состояние вне конструктора, но все же предпочитает делать это внутри конструктора.
Так что мне просто интересно, какой путь лучше и почему?
Я считаю, что это вопрос личных предпочтений. Транспортированный вывод одинаков с точки зрения семантики.
Они эквивалентны, потому что предложение поля класса является синтаксическим сахаром для кода тела конструктора.
В случае, если нет необходимости в явном конструкторе (создании временных локальных переменных и т.д.), constructor
может быть опущен в пользу полей класса.
Проблема с явным конструктором заключается в том, что аргументы super
(props
) часто опускаются по ошибке, это может привести к проблемам:
constructor() {
super();
this.state = { foo: this.props.foo } // this.props is undefined
}
Явный конструктор может быть полезен для удобства чтения. Методы обычно помещаются ниже constructor
, даже со стрелками. Это не будет работать должным образом, поскольку поля класса назначаются в том порядке, в котором они были перечислены:
state = { foo: { method: this.someMethod } } // this.someMethod is undefined
someMethod = () => ...;
В этом случае явный конструктор может привести к более читаемому коду:
constructor(props) {
super(props);
// <-- this is the place where this.someMethod is really assigned
this.state = { foo: { method: this.someMethod } }
}
someMethod = () => ...;
В коде Дэн есть тонкая ошибка, поэтому я рекомендую использовать инициализаторы, когда это возможно. Конструкторы реактивных компонентов принимают два аргумента - реквизиты и контекст. Он не передавал его родительскому конструктору, и его можно было легко упустить другим разработчиком, которому это было необходимо.
Иногда у вас нет выбора, например, когда инициализатор зависит от аргументов конструктора, поэтому просто не забудьте передать все аргументы родительскому.
Попробовав несколько вещей, похоже, что у Реакта нет проблемы, о которой я думал. Вы можете передать все, что хотите, родительскому конструктору, и все будет хорошо. Например:.
class MyComponent extends React.Component {
constructor(props) {
super({})
}
render() {
// this.props will still be set correctly here
}
}
Я по-прежнему рекомендую использовать инициализаторы, поскольку не нужно вызывать родительский конструктор, о чем меньше думать.