Когда важно передать props
в super()
и почему?
class MyComponent extends React.Component {
constructor(props) {
super(); // or super(props) ?
}
}
Когда важно передать props
в super()
и почему?
class MyComponent extends React.Component {
constructor(props) {
super(); // or super(props) ?
}
}
Есть только одна причина, когда нужно передавать props
в super()
:
Когда вы хотите получить доступ к this.props
в конструкторе.
Passing:
class MyComponent extends React.Component {
constructor(props) {
super(props)
console.log(this.props)
// -> { icon: 'home', … }
}
}
Не проходя:
class MyComponent extends React.Component {
constructor(props) {
super()
console.log(this.props)
// -> undefined
// Props parameter is still available
console.log(props)
// -> { icon: 'home', … }
}
render() {
// No difference outside constructor
console.log(this.props)
// -> { icon: 'home', … }
}
}
Обратите внимание, что передача или не передача props
в super
не влияет на последующее использование this.props
вне constructor
. То есть, render
, shouldComponentUpdate
или обработчики событий всегда имеют к нему доступ.
Об этом прямо говорится в одном ответе Софи Альперт на аналогичный вопрос.
Документация - Состояние и жизненный цикл, Добавление локального состояния в класс, пункт 2 - рекомендует:
Компоненты класса всегда должны вызывать базовый конструктор с
props
.
Однако причина не указана. Мы можем предположить, что это либо из-за подклассов, либо для будущей совместимости.
(Спасибо @MattBrowne за ссылку)
В этом примере вы расширяете класс React.Component
и по спецификации ES2015, конструктор дочернего класса не может использовать this
пока не будет вызван вызов super()
; Кроме того, конструкторы классов ES2015 должны вызывать super()
если они являются подклассами.
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
В отличие от этого:
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Более подробно в соответствии с этим отличным ответом на переполнение стека
Вы можете увидеть примеры компонентов, созданных путем расширения класса React.Component
который не вызывает super()
но вы заметите, что у них нет constructor
, поэтому он не нужен.
class MyOtherComponent extends React.Component {
render() {
return <div>Hi {this.props.name}</div>;
}
}
Одна из проблем, которые я видел у некоторых разработчиков, с которыми я говорил, заключается в том, что компоненты, которые не имеют constructor
и поэтому не называют super()
нигде, все еще имеют this.props
доступные в методе render()
. Помните, что это правило и необходимость создания this
связывания для constructor
применимы только к constructor
.
Когда вы передаете props
в super
, реквизиты присваиваются this
. Взгляните на следующий сценарий:
constructor(props) {
super();
console.log(this.props) //undefined
}
Как всегда, когда вы делаете:
constructor(props) {
super(props);
console.log(this.props) //props will get logged.
}
В соответствии с исходным кодом
function ReactComponent(props, context) {
this.props = props;
this.context = context;
}
вы должны проходить props
каждый раз, когда у вас есть реквизит, и вы не помещаете их в this.props
вручную.
Дан Абрамов написал статью на эту тему:
Почему мы пишем супер (реквизит)?
И суть в том, что полезно иметь привычку передавать его, чтобы избежать этого сценария, что, честно говоря, я не вижу, что это вряд ли произойдет:
// Inside React
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// Inside your code
class Button extends React.Component {
constructor(props) {
super(); // 😬 We forgot to pass props
console.log(props); // ✅ {}
console.log(this.props); // 😬 undefined
}
// ...
}
При реализации функции constructor()
внутри компонента React требуется требование super()
. Имейте в виду, что ваш компонент MyComponent
расширяет или заимствует функциональность из базового класса React.Component
.
Этот базовый класс имеет собственную constructor()
функцию, которая имеет внутри нее некоторый код, чтобы настроить наш компонент React для нас.
Когда мы определяем функцию constructor()
внутри нашего класса MyComponent
, мы по существу переопределяем или заменяем функцию constructor()
которая находится внутри класса React.Component
, но нам все равно нужно убедиться, что весь код установки внутри этого constructor()
функция все еще вызвана.
Таким образом, чтобы React.Component
функцию React.Component
constructor()
, мы вызываем super(props)
. super(props)
является ссылкой на функцию constructor()
родителей constructor()
, вот и все.
Мы должны добавлять super(props)
каждый раз, когда мы определяем функцию constructor()
внутри компонента класса.
Если мы не увидим ошибку, говорящую, что мы должны назвать super(props)
.
Вся причина для определения этого constructor()
funciton заключается в инициализации нашего объекта состояния.
Поэтому, чтобы инициализировать наш объект состояния, под супер-вызовом я собираюсь написать:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
// React says we have to define render()
render() {
return <div>Hello world</div>;
}
};
Таким образом, мы определили наш метод constructor()
, инициализировали наш объект состояния, создав объект JavaScript, присвоив ему свойство или пару ключ/значение, присвоив ему результат this.state
. Теперь, конечно, это просто пример, поэтому я действительно не назначил пару ключ/значение объекту state, его просто пустой объект.
Вот скрипка, которую я сделал:jsfiddle.net. Это показывает, что реквизиты назначаются не в конструкторе по умолчанию. Насколько я понимаю, они учтены в методе React.createElement
. Следовательно, super(props)
следует вызывать только тогда, когда конструктор суперкласса вручную присваивает props
- this.props
. Если вы просто расширите React.Component
, вызов super(props)
ничего не сделает с реквизитом. Возможно, это будет изменено в следующих версиях React.
super()
используется для вызова родительского конструктора.
super(props)
передаст props
родительскому конструктору.
В вашем примере super(props)
вызовет конструктор React.Component
, передав в качестве аргумента props
.
Более подробная информация о super
:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super
Здесь мы не получим это в конструкторе, чтобы он возвращался undefined, но мы можем получить это за пределами функции конструктора
class MyComponent extends React.Component {
constructor() {
console.log(this); // Reference Error i.e return undefined
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Если мы используем super(), то мы можем также получить "эту" переменную внутри конструктора
class MyComponent extends React.Component {
constructor() {
super();
console.log(this); // this logged to console
}
render() {
return <div>Hello {this.props.name}</div>;
}
}
Поэтому, когда мы используем super(); мы сможем получить это, но this.props не будет определено в конструкторе. Но кроме конструктора, this.props не будет возвращать неопределенные.
Если мы используем супер (реквизит), то мы можем также использовать значение this.props внутри конструктора
Если вы хотите использовать this.props в конструкторе, вам нужно передать реквизиты супер. В противном случае это не имеет значения, поскольку React устанавливает.props на экземпляр извне сразу после вызова конструктора.
Для реагирующей версии 16.6.3 мы используем super (props) для инициализации имени элемента состояния : this.props.name
constructor(props){
super(props);
}
state = {
name:this.props.name
//otherwise not defined
};