Яка різниця між "super ()" та "super (реквізит)" в React при використанні класів es6?


Відповіді:


709

Є лише одна причина, коли потрібно переходити propsдо super():

Коли ви хочете отримати доступ this.propsу конструкторі.

Проходження:

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 за посилання)


16
Я думаю, ви правильні, незважаючи на інші відповіді, які отримують більше голосів. this.propsне undefinedбуде передано до super(). У будь-якому випадку, це не впливає пізніше рендеринга або наявність this.propsв render()функції.
Мікрос

3
@Rotareti, ні, насправді решта класу не залежить від цієї конструкції, в цьому суть. Компонент отримує реквізит іншим способом, як за параметром конструктора. А оскільки ви передаєте початкові реквізити super, ви посилаєтесь на них у конструкторі.
Робін Покорний

7
Відповідно до документації React, ви завжди повинні переходити propsдо super(): facebook.github.io/react/docs/… . Я не впевнений, чому, оскільки, як ви зазначаєте, this.propsдоступний і іншими способами ... можливо, вони рекомендують це для подальшої сумісності, якщо майбутні версії React можуть захотіти щось зробити propsв конструкторі?
Метт Браун

23
Можливо, я просто відкриваю банку з хробаками, але навіщо взагалі переходити propsдо цього, superколи, як ви вказали, propsпараметр доступний нам для використання в конструкторі та this.propsпрацює скрізь? Чи взагалі є користь від використання this.propsпонад просто props? Чи погана практика деструкції відключена propsв конструкторі? Я думаю , що я до сих пір не в змозі побачити випадок , коли ви коли - небудь необхідно пройти , propsщоб super, але я готовий посперечатися , що це тільки моє невігластво, ха.
indiesquidge

9
Якщо ви використовуєте super(props), ви можете викликати методи, які використовують this.props у конструкторі , наприклад this.doStuffUsingThisDotProps(), без необхідності передавати параметр реквізиту на ці методи / функції. Я просто написав це конструктором, який, здавалося б, вимагав би від мене спочатку скористатися super(props), відповідно до відповідей на це питання.
Віктор Заманян

54

У цьому прикладі ви розширюєте 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.


15
Дякую за вашу відповідь, але це не відповідає на моє оригінальне запитання (різниця між super()і super(props)).
Мішко Морошко

46

Коли ви переходите propsдо super, реквізит призначається this. Погляньте на такий сценарій:

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

Як колись:

constructor(props) {
    super(props);
    console.log(this.props) //props will get logged.
}

Найкраща відповідь у списку.
Басварадж Хадімані

Ця відповідь наполовину правильна. Цей приклад лише для конструкторського методу. Наприклад, навіть якщо ви не пишете супер (реквізит), цей.props за методом візуалізації все одно буде призначений і доступний. Єдина причина, згадана вище, - це використання цього.props в конструкторі.
Офер

12

Відповідно до вихідного коду

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

ви повинні проходити propsкожен раз, коли у вас є реквізити, і ви не вводите їх this.propsвручну.


1
Мені досі не зрозуміло з цього приводу. якщо ви подивитеся на ці два компоненти , ви можете бачити один дзвінок, super(props)а інший - ні. Але їхні споживачі обидва встановлюють реквізит. Яка різниця?
Kyeotic

Це означає це this.props = propsі super(props)є те саме?
reectrix

1
Це не правда. ReactElement насправді встановлюється this.propsвід "зовні" - незалежно від того, що робиться в конструкторі.
Робін Покорний

11

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

Чому ми пишемо супер (реквізити)?

І суть у тому, що корисно мати звичку передавати його, щоб уникнути цього сценарію, якщо чесно, я не бачу, що це навряд чи станеться:

// 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 
  }
  // ...
}

8

super() використовується для виклику батьківського конструктора.

super(props)перейде propsдо батьківського конструктора.

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

Детальніше на сайті super: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super


18
Так, це робить. Але чому ? І коли в React потрібна одна з двох форм?
Бергі

7

При реалізації constructor()функції всередині компонента React super()є вимогою. Майте на увазі, що ваш MyComponentкомпонент розширює або запозичує функціональні можливості у React.Componentбазового класу.

Цей базовий клас має власну constructor()функцію, яка містить якийсь код всередині нього, щоб встановити наш компонент React для нас.

Коли ми визначаємо constructor()функцію всередині нашого MyComponentкласу, ми, по суті, переосмислюємо або замінюємо constructor()функцію, яка знаходиться всередині React.Componentкласу, але нам все одно потрібно переконатися, що весь код настройки всередині цієї constructor()функції все ще викликається.

Отже, щоб переконатися, що функція React.Component's constructor()викликається, ми викликаємо super(props). super(props)є посиланням на функцію батьків constructor(), ось і все.

Ми повинні додавати super(props)кожен раз, коли ми визначаємо constructor()функцію всередині компонента на основі класу.

Якщо ми цього не зробимо, ми побачимо помилку про те, що нам потрібно зателефонувати super(props).

Вся причина визначення цього функціоналу constructor()полягає в ініціалізації нашого державного об'єкта.

Тож для того, щоб ініціалізувати наш державний об’єкт, під супер дзвінком я збираюся написати:

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. Тепер, звичайно, це лише приклад, тому я дійсно не присвоїв парі ключ / значення об’єкту стану, його просто порожній об’єкт.


4

Ось загадка, яку я склав: jsfiddle.net . Це показує, що реквізити призначаються не в конструкторі за замовчуванням. Як я розумію, вони використовуються в методі React.createElement. Тому super(props)слід називати тільки тоді , коли конструктор вручну assings суперкласу propsз this.props. Якщо ви просто продовжите React.Componentвиклик super(props), нічого не буде робити з реквізитом. Можливо, це буде змінено в наступних версіях React.


3

Тут ми не отримаємо цього в конструкторі, тому він повернеться невизначеним, але ми зможемо отримати це поза функцією конструктора

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 буде невизначено в конструкторі. Але крім конструктора, цей.props не повернеться невизначеним.

Якщо ми використовуємо супер (реквізит), то можемо використовувати і це значення.пропс всередині конструктора

Відповідь Софі Альперт

Якщо ви хочете використовувати this.props в конструкторі, вам потрібно передати реквізит супер. В іншому випадку це не має значення, оскільки React встановлює .props на екземпляр ззовні відразу після виклику конструктора.


3

Для реагування версії 16.6.3 ми використовуємо супер (реквізит) для ініціалізації імені елемента стану : this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.