В чем разница между «super ()» и «super (props)» в React при использовании классов es6?

393

Когда важно передать props в super() и почему?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}
Теги:
ecmascript-6

10 ответов

546
Лучший ответ

Есть только одна причина, когда нужно передавать 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 за ссылку)

  • 10
    Я думаю, что вы правы, несмотря на то, что другие ответы набрали больше голосов. this.props не undefined если не передано super() . В любом случае, это не влияет на последующий рендеринг или доступность this.props в функции render() .
  • 0
    Я нахожу ответ запутанным, потому что, если я передаю props super, я получаю доступ к this.props не только в `constructor (), но и во всем классе. Я не нахожу это излишним.
Показать ещё 17 комментариев
47

В этом примере вы расширяете класс 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.

  • 14
    Большое спасибо за ваш ответ, но он не отвечает на мой первоначальный вопрос (разница между super() и super(props) ).
37

Когда вы передаете props в super, реквизиты присваиваются this. Взгляните на следующий сценарий:

constructor(props) {
    super();
    console.log(this.props) //undefined
}

Как всегда, когда вы делаете:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}
  • 0
    Лучший ответ в списке.
11

В соответствии с исходным кодом

function ReactComponent(props, context) {
  this.props = props;
  this.context = context;
}

вы должны проходить props каждый раз, когда у вас есть реквизит, и вы не помещаете их в this.props вручную.

  • 1
    Я до сих пор не ясно по этому вопросу. если вы посмотрите на эти два компонента , вы увидите, что один вызывает super(props) а другой нет. Но их потребители устанавливают реквизит. В чем разница?
  • 0
    Значит ли это, что this.props = props и super(props) - это одно и то же?
Показать ещё 1 комментарий
5

super() используется для вызова родительского конструктора.

super(props) передает props родительскому конструктору.

Из вашего примера, super(props) назвал бы React.Component конструктор передавая props в качестве аргумента.

Дополнительная информация о super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

  • 17
    Да, это то, что он делает. Но почему ? И когда в React требуется одна из двух форм?
4

Вот скрипка, которую я сделал: https://jsfiddle.net/beshanoe/zpxbLw4j/1/. Он показывает, что реквизит назначается не в конструкторе по умолчанию. Насколько я понимаю, они описаны в методе React.createElement. Следовательно, super(props) следует вызывать только тогда, когда конструктор суперкласса вручную устанавливает props в this.props. Если вы просто растянете вызов React.Component super(props), он ничего не сделает с помощью реквизита. Возможно, он будет изменен в следующих версиях React.

3

При реализации функции 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, его просто пустой объект.

1

Дан Абрамов написал статью на эту тему:

https://overreacted.io/why-do-we-write-super-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 
  }
  // ...
}
1

Здесь мы не получим это в конструкторе, чтобы он возвращался 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 на экземпляр извне сразу после вызова конструктора.

0

Для реагирующей версии 16.6.3 мы используем super (props) для инициализации имени элемента состояния : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};

Ещё вопросы

Сообщество Overcoder
Наверх
Меню