[TOC]
# Making a functional or stateless component
So far, we have only learned how to create *class components* in React. These components are useful when you need to handle local state, but in some cases, we will need to render static markup. For static components, we need to use functional components, also known as stateless components . This will improve the performance of our application.
到目前为止,我们只学习了如何在React中创建类组件。当您需要处理本地状态时,这些组件非常有用,但是在某些情况下,我们需要渲染静态标记。对于静态组件,我们需要使用 functional components ,也称为stateless components 无状态组件。这将提高应用程序的性能。
In the *Passing props to a component and validating them with PropTypes* recipe, we created some layout components (`Header`, `Content`, and `Footer`).
These components, as you may imagine, are frequently not dynamic (unless you want to have a toggle menu or some user information in the header), so in this case, we can convert them into functional components.
你可能想到,这些组件通常不是动态的(除非你想在标题中有一个切换菜单或一些用户信息),所以在这种情况下,我们可以将它们转换为 功能组件。
# getInitialState VS constructor
`React.createClass`创建了一个叫做`getInitialState`的函数,它只做一件事,那就是返回一个包含初始化状态的对象。
使用`React.Component`后,`getInitialState`函数被抛弃了,我们在`constructor`中像创建初始化属性一样声明了所有状态,我认为这样更加像 JavaScript 并且更少地驱动了“API”。
也就是说,`React.createClass`创建的组件,其状态`state`是通过`getInitialState`方法来配置组件相关的状态;`React.Component`创建的组件,其状态`state`是在`constructor`中像初始化组件属性一样声明的。
# Mixins
Mixins(混入)是面向对象编程OOP的一种实现,其作用是为了复用共有的代码,将共有的代码通过抽取为一个对象,然后通过Mixins进该对象来达到代码复用。如果我们使用 ES6 的方式来创建组件,那么 React mixins 的特性将不能被使用了。
## React.createClass
使用`React.createClass`的话,我们可以在创建组件时添加一个叫做`mixins`的属性,并将可供混合的类的集合以数组的形式赋给`mixins`。
```
import React from 'react';
var SomeMixin = {
doSomething() {
}
};
const Contacts = React.createClass({
mixins: [SomeMixin],
handleClick() {
this.doSomething(); // use mixin
},
render() {
return (
<div onClick={this.handleClick}></div>
);
}
});
export default Contacts;
```
## React.Component
**但在 ES6 中,`mixins`特性不被支持。但是 React 社区提供一个全新的方式来取代 Mixins ,那就是 Higher-Order Components(高阶组件)**。 那么什么是高阶组件呢?其实它和高阶函数的概念类似,就是一个会返回组件的组件。或者更确切地说,它其实是一个会返回组件的函数。就像这样:
```
const HigherOrderComponent = (WrappedComponent) => {
return class WrapperComponent extends Component {
render() {
//do something with WrappedComponent
}
}
}
```
做为一个高阶组件,可以在原有组件的基础上,对其增加新的功能和行为。我们一般希望编写的组件尽量纯净或者说其中的业务逻辑尽量单一。
但是如果各种组件间又需要增加新功能,如打印日志,获取数据和校验数据等和展示无关的逻辑的时候,这些公共的代码就会被重复写很多遍。
因此,我们可以抽象出一个高阶组件,用以给基础的组件增加这些功能,类似于插件的效果。具体细节可以[参考这篇文章](https://leozdgao.me/chushi-hoc/)。
# 无状态组件
无状态组件一般会搭配**高阶组件**(简称:HOC)一起使用,高阶组件用来托管`state`,Redux 框架就是通过`store`管理数据源和所有状态,其中所有负责展示的组件都使用无状态函数式的写法。
这种模式被鼓励在大型项目中尽可能以简单的写法 来分割原本庞大的组件,**而未来 React 也会面向这种无状态的组件进行一些专门的优化,比如避免无意义的检查或内存分配。所以建议大家尽可能在项目中使用无状态组件。**
无状态组件内部其实是可以使用 `ref` 功能的,虽然不能通过 `this.refs` 访问到,但是可以通过将 `ref` 内容保存到无状态组件内部的一个本地变量中获取到。
例如下面这段代码可以使用 `ref` 来获取组件挂载到DOM中后所指向的DOM元素:
```
function TestComp(props){
let ref;
return (
<div ref={(node) => ref = node}></div>
)
}
```