使用哪种ReactJS语法:React.createClass还是ES6 extends?

8

我是ReactJS的初学者。我在各个网站上阅读了许多文档和电子书籍,了解到ReactJS有两种语法。例如:

React.createClass({
  displayName: 'Counter',
  getDefaultProps: function(){
    return {initialCount: 0};
  },
  getInitialState: function() {
    return {count: this.props.initialCount} 
  },
  propTypes: {initialCount: React.PropTypes.number},
  tick() {
    this.setState({count: this.state.count + 1});
  },
  render() {
    return (
      <div onClick={this.tick}>
        Clicks: {this.state.count}
      </div>
    );
  }
});

这个版本使用了ES6编写:

class Counter extends React.Component {
  static propTypes = {initialCount: React.PropTypes.number};
  static defaultProps = {initialCount: 0};

  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }

  state = {count: this.props.initialCount};
  tick() {
    this.setState({count: this.state.count + 1});
  }

  render() {
    return (
      <div onClick={this.tick.bind(this)}>
        Clicks: {this.state.count}
      </div>
    );
  }
}

如何更好地使用ReactJS?但我发现这些库和在Github上的应用程序通常会使用大量ES6。


当你有机会时,你可以将标题设置为“React.createClass vs. React.Component”,我认为这会非常好。@PhamMinhTan - prosti
3个回答

11
第二种方法可能是正确的选择,因为Facebook已经表示他们最终会弃用React.createClass方法。
React v0.13 release notes可以看到:
我们的最终目标是让ES6类完全取代React.createClass方法,但在语言中没有当前mixin使用情况和类属性初始化器的替代方案之前,我们不打算废弃React.createClass方法。
个人认为第二种方法也更容易阅读代码,但这显然是一个更主观的原因。
但是,如上所述,重要的是要注意ES6格式不支持Mixins,因此,如果您需要mixin,则需要使用createClass格式来创建该组件。 Todd Motto的“React.createClass versus extends React.Component”一文对两种语法之间的差异有一些很好的信息。值得阅读以了解两种语法之间的this关键字行为差异的讨论。

编辑:下面Dan Caragea的帖子提出了一些非常好的观点,应该予以考虑。

第三种选择...

还有一种定义React组件的方法,称为“无状态函数”在React文档中,通常称为“无状态功能组件”或“功能性无状态组件”。以下是文档中的示例:

function HelloMessage(props) {
  return <div>Hello {props.name}</div>;
}

将组件定义为函数意味着每次都会重新创建它,因此它没有持续的内部状态。这使得组件更易于理解和测试,因为对于给定的属性集(props),组件的行为始终相同,而不是由于内部状态的值而可能在运行时有所变化。

当使用单独的状态管理方法,例如Redux时,此方法特别有效,并确保Redux的时间旅行将产生一致的结果。功能性无状态组件还使实现撤消/重做等功能更加简单。


1
感谢@tom的信息和你的主观理由。之前,我喜欢使用JSX语法编写我的ReactJS项目。但现在,我应该重新考虑使用ES6语法来决定编写ReactJS。 :) 谢谢 - Pham Minh Tan
我喜欢使用的方式是组合方式,React.createClass。ES6类只是糖,在创建工厂时没有任何实际价值(至少对我来说是这样)。也许装饰器在ES6类中很方便,但是可以通过使用高阶函数轻松解决。因此,我的赌注是ES6 + React.createClass === 胜利。 - gor181

5

我曾经在工作中使用过 React.createClass,也在我的个人项目中使用了ES6类。我发现后者更易于阅读,但有时会错过前者的简单性和心理平静感。 需要注意的是,采用基于类的方法时,技术上来说,静态定义的propTypes和defaultProps属于ES7而不是ES6,这可能会在ES7最终确定之前发生变化。 纯ES6方法是声明propTypes/defaultProps如下:

class Counter extends React.Component {
...
}
Counter.propTypes = {...};
Counter.defaultProps = {...};

你还需要记得在render(或者其他需要使用this的方法中)绑定onClick事件。几乎可以肯定有些地方你会忘记绑定。而使用createClass时,React会自动绑定所有调用。 另一个ES7提案可以使事情变得更容易,但你仍然需要记住在每个地方都要写: <div onClick={::this.tick}> 这个语法将this绑定到tick。 当然,你需要在babel配置中选择stage 0来使用所有这些ES7提议。
关于mixins...有一些可接受的方式与类一起使用mixins。一个精妙的方法是mixWith.js,但你也可以尝试ES7装饰器、HOC,甚至Object.assign() :)
总之,我认为类的方法并没有带来真正的价值,你可以继续使用旧的和成熟的createClass直到你对React有了很好的理解。然后你可以玩弄类和ES6/7/100。在他们废弃createClass之前还有很长的时间。

0

我从React ES6 +分期样式开始,当你说在React中一切都是组件时,听起来很不错。我喜欢这种class的组织方式。

enter image description here

因为在ES6中,只有方法可以在class内部定义。如果你想在纯粹的ES6中定义属性,它们必须在类外部定义。就像这里的例子一样:
export class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {count: props.initialCount};
  }
  tick() {
    this.setState({count: this.state.count + 1});
  }
  render() {
    return (
      <div onClick={this.tick.bind(this)}>
        Clicks: {this.state.count}
      </div>
    );
  }
}
Counter.propTypes = { initialCount: React.PropTypes.number };
Counter.defaultProps = { initialCount: 0 };

这就是为什么在ES6中,propTypes部分位于类定义之外。
但是如果你使用ES7,你可以在class内部毫无问题地定义静态和非静态属性。
// ES7
export class Counter extends React.Component {
  static propTypes = { initialCount: React.PropTypes.number };
  static defaultProps = { initialCount: 0 };
  state = { count: this.props.initialCount };
  tick() {
    this.setState({ count: this.state.count + 1 });
  }
  render() {
    return (
      <div onClick={this.tick.bind(this)}>
        Clicks: {this.state.count}
      </div>
    );
  }
}

在ES7中,你也可以使用隐式绑定技巧来处理方法,就像这里所示:

return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
);

旧的 React v0.13 或 ES5 风格是这样的。

enter image description here

React.createClass 中,所有的方法都会自动绑定 this。
这可能会让 JavaScript 开发人员感到有些困惑,因为这不是原生的 JavaScript 行为。
这就是我们写的内容:
class Counter extends React.Component {
  constructor() {
    super();
    this.tick = this.tick.bind(this);
  }
  tick() {
    ...
  }
  ...
}

或者使用一些技巧,通过属性初始化器语法来完成相同的任务。

class Counter extends React.Component {
  tick = () => {
    ...
  }
  ...
}

总结

对于新手来说,我认为最新的风格是更好的选择。


关于 Mixins

此处所述:

ES6 没有任何 mixin 支持。因此,当您使用 ES6 类与 React 时,不支持 mixins。 我们还发现了许多在使用 mixins 的代码库中存在的问题,并不建议在新代码中使用它们。 本节仅供参考。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接