;
}
});
// good
class Listing extends React.Component {
// ...
render() {
return
{this.state.hello}
;
}
}
```
如果你的模块没有状态或是没有引用`refs`, 推荐使用普通函数(非箭头函数)而不是类:
```jsx
// bad
class Listing extends React.Component {
render() {
return
{this.props.hello}
;
}
}
// bad (relying on function name inference is discouraged)
const Listing = ({ hello }) => (
{hello}
);
// good
function Listing({ hello }) {
return
{hello}
;
}
```
## Mixins
- [不要使用 mixins](https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html).
> 为什么? Mixins 会增加隐式的依赖,导致命名冲突,并且会以雪球式增加复杂度。在大多数情况下Mixins可以被更好的方法替代,如:组件化,高阶组件,工具模块等。
## Naming 命名
- **扩展名**: React模块使用 `.jsx` 扩展名.
>eslint: [`react/jsx-filename-extension`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-filename-extension.md)
- **文件名**: 文件名使用帕斯卡命名. 如, `ReservationCard.jsx`.
- **引用命名**: React模块名使用帕斯卡命名,实例使用骆驼式命名. eslint: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md)
```jsx
// bad
import reservationCard from './ReservationCard';
// good
import ReservationCard from './ReservationCard';
// bad
const ReservationItem = ;
// good
const reservationItem = ;
```
- **模块命名**: 模块使用当前文件名一样的名称. 比如 `ReservationCard.jsx` 应该包含名为 `ReservationCard`的模块. 但是,如果整个文件夹是一个模块,使用 `index.js`作为入口文件,然后直接使用 `index.js` 或者文件夹名作为模块的名称:
```jsx
// bad
import Footer from './Footer/Footer';
// bad
import Footer from './Footer/index';
// good
import Footer from './Footer';
```
- **高阶模块命名**: 对于生成一个新的模块,其中的模块名 `displayName` 应该为高阶模块名和传入模块名的组合. 例如, 高阶模块 `withFoo()`, 当传入一个 `Bar` 模块的时候, 生成的模块名 `displayName` 应为 `withFoo(Bar)`.
> 为什么?一个模块的 `displayName` 可能会在开发者工具或者错误信息中使用到,因此有一个能清楚的表达这层关系的值能帮助我们更好地理解模块发生了什么,更好地进行Debug。
```jsx
// bad
export default function withFoo(WrappedComponent) {
return function WithFoo(props) {
return ;
}
}
// good
export default function withFoo(WrappedComponent) {
function WithFoo(props) {
return ;
}
const wrappedComponentName = WrappedComponent.displayName
|| WrappedComponent.name
|| 'Component';
WithFoo.displayName = `withFoo(${wrappedComponentName})`;
return WithFoo;
}
```
- **属性命名**: 避免使用DOM相关的属性来用作其他的用途。
> 为什么?对于`style` 和 `className`这样的属性名,我们都会默认它们代表一些特殊的含义,如元素的样式,CSS class的名称。在你的应用中使用这些属性来表示其他的含义会使你的代码更难阅读,更难维护,并且可能会引起bug。
```jsx
// bad
// good
```
## Declaration 声明模块
- 不要使用 `displayName` 来命名React模块,而是使用引用来命名模块, 如 class 名称.
```jsx
// bad
export default React.createClass({
displayName: 'ReservationCard',
// stuff goes here
});
// good
export default class ReservationCard extends React.Component {
}
```
## Alignment 代码对齐
- 遵循以下的JSX语法缩进/格式. eslint: [`react/jsx-closing-bracket-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md) [`react/jsx-closing-tag-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-tag-location.md)
```jsx
// bad
// good
// if props fit in one line then keep it on the same line
// children get indented normally
// bad
{showButton &&
}
// bad
{
showButton &&
}
// good
{showButton && (
)}
// good
{showButton && }
// good
{someReallyLongConditional
&& anotherLongConditional
&& (
)
}
// good
{someConditional ? (
) : (
)}
```
## Quotes 单引号还是双引号
- 对于JSX属性值总是使用双引号(`"`), 其他均使用单引号(`'`). eslint: [`jsx-quotes`](http://eslint.org/docs/rules/jsx-quotes)
> 为什么? HTML属性也是用双引号, 因此JSX的属性也遵循此约定.
```jsx
// bad
// good
// bad
// good
```
## Spacing 空格
- 总是在自动关闭的标签前加一个空格,正常情况下也不需要换行. eslint: [`no-multi-spaces`](http://eslint.org/docs/rules/no-multi-spaces), [`react/jsx-tag-spacing`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-tag-spacing.md)
```jsx
// bad
// very bad
// bad
// good
```
- 不要在JSX `{}` 引用括号里两边加空格. eslint: [`react/jsx-curly-spacing`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-curly-spacing.md)
```jsx
// bad
// good
```
## Props 属性
- JSX 属性名使用小骆驼拼写法`camelCase`,如果属性名是一个 React 组件名,则使用大骆驼拼写法 `PascalCase`
```jsx
// bad
// good
```
- 如果属性值为 `true`, 可以直接省略. eslint: [`react/jsx-boolean-value`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-boolean-value.md)
```jsx
// bad
// good
// good
```
- `` 标签总是添加 `alt` 属性. 如果图片以presentation(感觉是以类似PPT方式显示?)方式显示,`alt` 可为空, 或者`` 要包含`role="presentation"`. eslint: [`jsx-a11y/alt-text`](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/alt-text.md)
```jsx
// bad
// good
// good
// good
```
- 不要在 `alt` 值里使用如 "image", "photo", or "picture"包括图片含义这样的词, 中文也一样. eslint: [`jsx-a11y/img-redundant-alt`](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/img-redundant-alt.md)
> 为什么? 屏幕助读器已经把 `img` 标签标注为图片了, 所以没有必要再在 `alt` 里说明了.
```jsx
// bad
// good
```
- 使用有效正确的 aria `role`属性值 [ARIA roles](https://www.w3.org/TR/wai-aria/roles#usage_intro). eslint: [`jsx-a11y/aria-role`](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/aria-role.md)
```jsx
// bad - not an ARIA role
// bad - abstract ARIA role
// good
```
- 不要在标签上使用 `accessKey` 属性. eslint: [`jsx-a11y/no-access-key`](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-access-key.md)
> 为什么? 屏幕助读器在键盘快捷键与键盘命令时造成的不统一性会导致阅读性更加复杂.
```jsx
// bad
// good
```
- 避免使用数组的 index 来作为 `key` 属性的值。
> 译者注:key 属性指名称为 `key` 的属性,即 `props.key`
应当使用稳定不变的 ID。(使用不稳定的 ID 是一个[反面模式](https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318),会降低性能、造成组件状态出错) 。特别是当元素的顺序可能改变的情况下,不应使用数组的 index 作为 `key`.
> 译者注:反面模式 (Anti-Pattern),指低效或是有待优化的软件设计模式。
```jsx
// bad
{todos.map((todo, index) =>
)}
// good
{todos.map(todo => (
))}
```
- 对于所有非必须的属性,总是手动去定义`defaultProps`属性.
> 为什么? propTypes 可以作为模块的文档说明, 并且声明 defaultProps 的话意味着阅读代码的人不需要去假设一些默认值。更重要的是, 显示的声明默认属性可以让你的模块跳过属性类型的检查.
```jsx
// bad
function SFC({ foo, bar, children }) {
return
{foo}{bar}{children}
;
}
SFC.propTypes = {
foo: PropTypes.number.isRequired,
bar: PropTypes.string,
children: PropTypes.node,
};
// good
function SFC({ foo, bar, children }) {
return