" super()"之间的区别是什么?和超级(道具)"在使用es6类的React中?

时间:2015-06-01 11:04:52

标签: reactjs ecmascript-6

什么时候将props传递给super(),为什么这么重要?

class MyComponent extends React.Component {
  constructor(props) {
    super(); // or super(props) ?
  }
}

10 个答案:

答案 0 :(得分:608)

只有一个原因需要将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的后续使用中,传递或不传递constructorrender 无影响。这是shouldComponentUpdateprops或事件处理程序始终可以访问它。

在一篇索菲·阿尔珀特的answer中明确地提到了类似的问题。

文档 - State and Lifecycle, Adding Local State to a Class, point 2 - 建议:

  

类组件应始终使用const调用基础构造函数。

但是,没有提供任何理由。我们可以推测它要么是因为子类化,要么是为了将来的兼容性。

(感谢@MattBrowne的链接)

答案 1 :(得分:49)

在此示例中,您正在扩展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>;
  }
}

根据this excellent stack overflow answer

提供更多详情

您可能会看到通过扩展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

答案 2 :(得分:39)

当您将props传递给super时,道具会被分配到this。请看下面的场景:

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

你怎么做:

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

答案 3 :(得分:11)

根据source code

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

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

答案 4 :(得分:6)

super()用于调用父构造函数。

super(props)会将props传递给父构造函数。

在您的示例中,super(props)会调用传递React.Component的{​​{1}}构造函数作为参数。

有关props的更多信息: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super

答案 5 :(得分:6)

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

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

答案 6 :(得分:4)

这是我做过的小提琴:https://jsfiddle.net/beshanoe/zpxbLw4j/1/。它显示默认情况下不在构造函数中分配道具。据我所知,他们在方法React.createElement中受到了帮助。因此,只有当超类的构造函数手动将super(props)传递给props时,才应调用this.props。如果您只是延长React.Component来电super(props)将无法使用道具。也许它会在React的下一个版本中被更改。

答案 7 :(得分:4)

在React组件中实现constructor()函数时,super()是必需的。请记住,您的MyComponent组件是从React.Component基类扩展或借用的功能。

该基类本身具有一个constructor()函数,该函数内部具有一些代码,可以为我们设置React组件。

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

因此,为了确保调用React.Component的{​​{1}}函数,我们调用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>; } }; 方法,通过创建JavaScript对象,为其分配属性或键/值对,并将其结果分配给constructor()来初始化状态对象。当然,现在这只是这里的一个示例,因此我没有真正为状态对象分配键/值对,它只是一个空对象。

答案 8 :(得分:2)

这里我们不会在构造函数中得到它,所以它将返回未定义,但是我们可以在构造函数之外获取它

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值

Sophie Alpert's Answer

  

如果要在构造函数中使用this.props,则需要传递   超级道具。否则没关系,因为React设置了.props   从外部调用实例后   构造函数。

答案 9 :(得分:1)

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

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