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

Ответы:

710

Есть только одна причина, когда нужно перейти 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()функции.
Micros
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 в конструкторе from , например this.doStuffUsingThisDotProps(), без необходимости передавать параметр props этим методам / функциям. Я просто написал конструктор, делающий это, что, по-видимому, потребовало бы, чтобы я 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.
}
Нахуш Фарканде
источник
Лучший ответ в списке.
Басаварадж Хадимани
Этот ответ наполовину правильный, этот пример только для метода конструктора. Например, даже если вы не пишете super (props), this.props в методе render все равно будет назначен и доступен. Единственная причина, упомянутая выше, заключается в использовании this.props в конструкторе.
Ofear
12

Согласно исходному коду

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

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

zerkms
источник
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

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

При реализации constructor()функции внутри компонента React, super()это требование. Имейте в виду, что ваш MyComponentкомпонент расширяет или заимствует функциональность из React.Componentбазового класса.

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

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

Чтобы убедиться, что функция React.Components 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)должен вызываться только тогда, когда конструктор суперкласса вручную указывает propsна this.props. Если вы просто продлите React.Componentвызов super(props), вы ничего не сделаете с реквизитом. Возможно, это будет изменено в следующих версиях React.

beshanoe
источник
3

Здесь мы не получим это в конструкторе, поэтому он вернет 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 (), то мы можем также извлечь переменную "this" внутри конструктора

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 не будет возвращать undefined.

Если мы используем super (props), то мы можем также использовать значение this.props внутри конструктора

Ответ Софи Альперт

Если вы хотите использовать this.props в конструкторе, вам нужно передать реквизиты super. В противном случае это не имеет значения, потому что React устанавливает .props для экземпляра извне сразу после вызова конструктора.

ВИКАС КОЛИ
источник
3

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

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
шубхам капур
источник