React.createClass 和 ES6 箭头函数的区别

22

我刚接触React,正在努力掌握语法。

我在React 15环境下进行开发(使用react-starterify模板),一直使用VERSION 2中的语法,但是我在Facebook的React页面上找到的大部分示例和教程都是VERSION 1。这两者之间有什么区别,我应该在什么情况下使用其中的一个而不是另一个?

VERSION 1

var MyComponent = React.createClass({
  render: function() {
    return (
      <ul>
        // some list
      </ul>
    );
  }
});

module.exports = MyOtherComponent;

版本 2

const MyComponent = () => (
  <ul>
    // some list
  </ul>
);

export default MyComponent;

2
第一个版本允许您钩入像componenDidMountshouldComponentUpdate等生命周期方法。第二个版本基本上只是render函数。默认情况下使用第二个版本,如果需要生命周期方法,请使用第一个版本。 - azium
1
请注意,createClass 是旧的类样式,现在您可以(应该)使用ES6类 - Aaron Beall
同时,在React Native中,createClass已经被弃用。 - Reza Ghorbani
2个回答

34
第二个代码是一个无状态函数组件,它是一种新的语法/模式,用于将组件定义为props的函数。它在React v0.14中被介绍。
您可以在官方React博客这里或官方React文档这里中了解更多信息。

这些组件的行为就像只定义了render方法的React类一样。由于没有为功能组件创建任何组件实例,因此添加到此类组件中的任何引用都将计算为null。功能组件没有生命周期方法,但您可以将.propTypes.defaultProps设置为函数的属性。

这种模式旨在鼓励创建这些简单组件,这些组件应构成您的应用程序的大部分。将来,我们还将能够通过避免不必要的检查和内存分配来针对这些组件进行性能优化。


  • 有什么不同?

    这种模式与“传统”模式相似,但您使用的是简单函数,而不是在类中定义的方法。当您想要将函数提取出类时(例如为了可读性和清洁度),这可能非常有用。

    需要注意的一点是,函数组件只是一个函数。它不是一个类。因此,没有全局的this对象。这意味着当您进行render时,您基本上正在创建一个ReactComponent的新实例,从而省略了这些JavaScript对象通过某些全局this相互通信的可能性。这也使得使用state和任何生命周期方法成为不可能的后果。



  • 我的应用程序如何受益?

    性能
    当您使用无状态功能组件时,React 足够聪明,可以省略所有“传统”的生命周期方法,这实际上提供了相当多的优化。React 团队已经表示,他们计划在未来实现进一步的优化,以减少内存分配和检查次数。

    适应性
    因为我们只谈论一个函数(而不是一个类),所以我们不需要担心 state、生命周期方法或其他依赖关系。给定参数,该函数将始终给出相同的输出。因此,在任何地方调整这样的组件非常容易,这也使得测试变得更加容易。

    使用 React 的无状态功能组件,每个组件都可以轻松地进行单独测试。不需要模拟、状态操作、特殊库或棘手的测试工具。

    鼓励最佳实践
    React 经常被比作 MVC 模式中的 V,因为它用于创建视图。创建组件的“传统”方式使得容易将业务逻辑(例如使用 stateref)插入到本应只处理呈现逻辑的组件中。它们鼓励懒惰和编写不良代码。然而,无状态功能组件几乎不可能采取这种捷径,并强制采用更好的方法。


  • 我应该在什么情况下使用其中之一?

    通常情况下,建议尽可能使用新模式!如果您只需要一个 render 方法,但没有生命周期方法或 state,请使用此模式。当然,有时候您确实需要使用 state,在这种情况下,使用传统模式也是可以的。

    Facebook 建议在渲染静态表示组件时使用无状态组件。然后,如果需要某种状态,请简单地将其包装在有状态组件中,通过使用其 state 并向无状态组件发送 props 来管理它们。


1
非常感谢您详尽的回答。我正在使用Granze的react-starterify git作为我的起点,它专门使用const框架...但是对于一个动态Web应用程序来说,似乎访问状态和生命周期对于许多事情都至关重要,不是吗?我注意到在App.js文件中有一个"App.propTypes = { children: React.PropTypes.object }"。也许这是为了存储跨组件数据? - Kirk Ross
我没有使用过 react-starterify,但你所提到的代码片段很可能只是一个类型声明。也许有经验的 react-starterify 用户可以帮忙解释一下。 - Chris

2

从react 15.5.0版本开始,React.createClass将被弃用。他们建议您转移到ES2015类或使用箭头函数。

当React最初发布时,JavaScript中没有创建类的惯用方式,因此我们提供了自己的方式:React.createClass。

后来,随着ES2015的推出,类被添加到语言中,因此我们添加了使用JavaScript类创建React组件的功能。除了函数组件外,JavaScript类现在是在React中创建组件的首选方式。

对于您现有的createClass组件,我们建议您将其迁移到JavaScript类。


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