在构造函数中定义状态还是使用 属性 初始化器更好?
Is it better to define state in constructor or using property initializers?
根据 this babel 文档,将 ES6+ 与 React 一起使用的正确方法是像这样初始化组件:
class Video extends React.Component {
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
}
state = {
loopsRemaining: this.props.maxLoops,
}
}
但是一些官方示例,例如 Dan Abramov 自己的 React DnD 模块,使用 ES6+ 但仍然在构造函数中定义状态:
constructor(props) {
super(props);
this.moveCard = this.moveCard.bind(this);
this.state = {
// state stuff
}
}
现在 Dan Abramov 作为 React 的重要贡献者,可能知道他可以在构造函数之外定义状态,但仍然选择在构造函数中进行。
所以我只是想知道哪种方法更好,为什么?
我认为这是个人喜好问题。转译后的输出在语义上是相同的。
Dan 的代码实际上有一个细微的错误,这就是为什么我建议尽可能使用初始化程序的原因。 React 组件构造函数有两个参数——props 和 the context。他没有将它传递给父构造函数,其他需要它的开发人员很容易错过它。
有时候你别无选择,比如当初始化器依赖于构造函数参数时,所以只要记住将所有参数传递给父级即可。
尝试了一些东西后,React 似乎没有我想的问题。你可以将任何你想要的传递给父构造函数,它会很好。例如:
class MyComponent extends React.Component {
constructor(props) {
super({})
}
render() {
// this.props will still be set correctly here
}
}
我仍然建议使用初始化器,因为不必调用父构造函数是一件需要考虑的事情。
它们是等价的,因为 class field proposal 是构造函数主体代码的语法糖。
如果不需要显式构造函数(创建临时局部变量等),可以省略 constructor
以支持 class 字段。
显式构造函数的问题是 super
个参数 (props
) 经常被错误地省略,这可能会导致问题:
constructor() {
super();
this.state = { foo: this.props.foo } // this.props is undefined
}
显式构造函数可能有利于提高可读性。方法常规放在constructor
下面,甚至是箭头属性。这不会按预期工作,因为 class 字段是按照它们列出的顺序分配的:
state = { foo: { method: this.someMethod } } // this.someMethod is undefined
someMethod = () => ...;
在这种情况下,显式构造函数可能会导致代码更具可读性:
constructor(props) {
super(props);
// <-- this is the place where this.someMethod is really assigned
this.state = { foo: { method: this.someMethod } }
}
someMethod = () => ...;
根据 this babel 文档,将 ES6+ 与 React 一起使用的正确方法是像这样初始化组件:
class Video extends React.Component {
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
videoSrc: React.PropTypes.string.isRequired,
}
state = {
loopsRemaining: this.props.maxLoops,
}
}
但是一些官方示例,例如 Dan Abramov 自己的 React DnD 模块,使用 ES6+ 但仍然在构造函数中定义状态:
constructor(props) {
super(props);
this.moveCard = this.moveCard.bind(this);
this.state = {
// state stuff
}
}
现在 Dan Abramov 作为 React 的重要贡献者,可能知道他可以在构造函数之外定义状态,但仍然选择在构造函数中进行。
所以我只是想知道哪种方法更好,为什么?
我认为这是个人喜好问题。转译后的输出在语义上是相同的。
Dan 的代码实际上有一个细微的错误,这就是为什么我建议尽可能使用初始化程序的原因。 React 组件构造函数有两个参数——props 和 the context。他没有将它传递给父构造函数,其他需要它的开发人员很容易错过它。
有时候你别无选择,比如当初始化器依赖于构造函数参数时,所以只要记住将所有参数传递给父级即可。
尝试了一些东西后,React 似乎没有我想的问题。你可以将任何你想要的传递给父构造函数,它会很好。例如:
class MyComponent extends React.Component {
constructor(props) {
super({})
}
render() {
// this.props will still be set correctly here
}
}
我仍然建议使用初始化器,因为不必调用父构造函数是一件需要考虑的事情。
它们是等价的,因为 class field proposal 是构造函数主体代码的语法糖。
如果不需要显式构造函数(创建临时局部变量等),可以省略 constructor
以支持 class 字段。
显式构造函数的问题是 super
个参数 (props
) 经常被错误地省略,这可能会导致问题:
constructor() {
super();
this.state = { foo: this.props.foo } // this.props is undefined
}
显式构造函数可能有利于提高可读性。方法常规放在constructor
下面,甚至是箭头属性。这不会按预期工作,因为 class 字段是按照它们列出的顺序分配的:
state = { foo: { method: this.someMethod } } // this.someMethod is undefined
someMethod = () => ...;
在这种情况下,显式构造函数可能会导致代码更具可读性:
constructor(props) {
super(props);
// <-- this is the place where this.someMethod is really assigned
this.state = { foo: { method: this.someMethod } }
}
someMethod = () => ...;