使用es6类时,React中的“ super()”和“ super(props)”有什么区别?


Answers:


709

只有一种原因需要传递propssuper()

当您要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。也就是说rendershouldComponentUpdate或事件处理程序始终可以访问它。

这是索菲·阿尔珀特(Sophie Alpert)对类似问题的回答中明确指出的。


建议使用“ 状态和生命周期,将本地状态添加到类,第2点”中的文档:

类组件应始终使用调用基本构造函数props

但是,没有提供任何理由。我们可以推测它是由于子类化还是出于将来的兼容性。

(感谢@MattBrowne的链接)


16
我认为您是正确的,尽管其他答案获得了更多的选票。this.propsundefined,除非传递给super()。无论哪种方式,它不会影响以后的渲染或可用性this.propsrender()功能。
Micros

3
@Rotareti,不,实际上,该类的其余部分不依赖于此构造,这就是重点。组件通过与构造函数参数不同的方式接收道具。并且由于您将初始道具传递给super,因此您在构造函数中已引用了它们。
罗宾·博科尼

7
根据React文档,您应该始终传递propssuper()facebook.github.io/react/docs/…。我不确定为什么,因为正如您指出的那样this.props,可以通过其他方法访问...也许他们建议这样做是为了将来的兼容性,以防React的未来版本可能需要props在构造函数中做一些事情?
马特·布朗

23
也许我只是打开一罐蠕虫在这里,但为什么永远传递propssuper时,正如你所指出,该props参数是正确的有可供我们在构造函数中使用,并且this.props工作在其他地方?this.props仅仅使用over 是否有好处propsprops在构造函数中进行销毁是不好的做法吗?我想我仍然没有看到您需要传递props给的情况super,但我敢打赌这只是我的无知,哈。
indiesquidge

9
如果使用super(props),则可以this.props 诸如的构造函数中调用使用in的方法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))。
Misha Moroshko

46

传递props给时super,道具将分配给this。看一下以下情况:

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

您何时做:

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

列表中最好的答案。
Basavaraj Hadimani

这个答案是正确的一半,此示例仅适用于构造方法。例如,即使您不编写super(props),render方法下的this.props仍将被分配并可用。上面提到的唯一原因是在构造函数中使用this.props时。
Ofear

12

根据源代码

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

props每次有道具时都必须通过,并且不要this.props手动将其放入。


1
我仍然不清楚。如果您查看两个组件,则可以看到一个调用super(props),而另一个则没有。但是他们的消费者都设置了道具。有什么区别?
Kyeotic

这是否意味着this.props = propssuper(props)同一件事?
reectrix 2015年

1
这不是真的。实际上,ReactElementthis.props从“ 外部”设置的,而与构造函数无关
罗宾·波高尼

11

Dan Abramov撰写了有关此主题的文章:

为什么我们要编写超级道具?

其要点是养成通过它避免这种情况的习惯,这很有帮助,说实话,我认为这种情况不太可能发生:

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


7

constructor()React组件内部实现功能时,super()是必需的。请注意,您的MyComponent组件正在扩展或借用React.Component基类。

这个基类有一个 constructor()自己功能,其中包含一些代码,可以为我们设置React组件。

当我们constructor()MyComponent类内部定义一个函数时,实质上constructor()是在重写或替换React.Component该类内部的函数,但是我们仍然需要确保constructor()仍调用该函数内部的所有设置代码。

因此,为了确保调用React.Componentconstructor()功能,我们调用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的下一版本中进行更改。


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(),那么我们也可以在构造函数中获取“ 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,则需要将props传递给super。否则没关系,因为React在调用构造函数后立即从外部在实例上设置.props。


3

对于React版本16.6.3,我们使用super(props)初始化状态元素名称:this.props.name

constructor(props){
    super(props);        
}
state = {
  name:this.props.name 
    //otherwise not defined
};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.