一份彙整了在 React 及 JSX 中被普遍使用的風格指南。
- 一個檔案只包含一個 React 元件。
- 總是使用 JSX 語法。
- 請別使用
React.createElement,除非你從一個不轉換 JSX 的檔案初始化。
- 使用
class extends React.Component,除非你有一個非常好的理由才使用 mixins。
eslint rules: react/prefer-es6-class.
```javascript
// bad
const Listing = React.createClass({
render() {
return <div />;
}
});
// good
class Listing extends React.Component {
render() {
return <div />;
}
}
```
- 副檔名:React 元件的副檔名請使用
jsx。 - 檔案名稱:檔案名稱請使用帕斯卡命名法。例如:
ReservationCard.jsx。 - 參考命名規範: React 元件請使用帕斯卡命名法,元件的實例則使用駝峰式大小寫:
eslint rules: react/jsx-pascal-case.
```javascript
// bad
import reservationCard from './ReservationCard';
// good
import ReservationCard from './ReservationCard';
// bad
const ReservationItem = <ReservationCard />;
// good
const reservationItem = <ReservationCard />;
```
-
元件命名規範:檔案名稱須和元件名稱一致。例如,
ReservationCard.jsx的參考名稱必須為ReservationCard。但對於目錄的根元件請使用index.jsx作為檔案名稱,並使用目錄名作為元件的名稱:// bad import Footer from './Footer/Footer'; // bad import Footer from './Footer/index'; // good import Footer from './Footer';
-
不要使用
displayName來命名元件。請使用參考來命名元件。// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
- JSX 語法請遵循以下的對齊風格
eslint rules: react/jsx-closing-bracket-location.
```javascript
// bad
<Foo superLongParam="bar"
anotherSuperLongParam="baz" />
// good
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
/>
// 如果 props 適合放在同一行,就將它們放在同一行上
<Foo bar="bar" />
// 通常子元素必須進行縮排
<Foo
superLongParam="bar"
anotherSuperLongParam="baz"
>
<Spazz />
</Foo>
```
- 總是在 JSX 的屬性使用雙引號(
"),但是所有的 JS 請使用單引號。
為什麼?JSX 屬性不能包含跳脫的引號,所以雙引號可以更容易輸入像
"don't"的連接詞。 一般的 HTML 屬性通常也使用雙引號而不是單引號,所以 JSX 屬性借鏡了這個慣例。
eslint rules: jsx-quotes.
```javascript
// bad
<Foo bar='bar' />
// good
<Foo bar="bar" />
// bad
<Foo style={{ left: "20px" }} />
// good
<Foo style={{ left: '20px' }} />
```
-
總是在自身結尾標籤前加上一個空格。
// bad <Foo/> // very bad <Foo /> // bad <Foo /> // good <Foo />
-
總是使用駝峰式大小寫命名 prop。
// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
-
Omit the value of the prop when it is explicitly
true.
eslint rules: react/jsx-boolean-value.
```javascript
// bad
<Foo
hidden={true}
/>
// good
<Foo
hidden
/>
```
- 當 JSX 的標籤有多行時請使用括號將它們包起來:
eslint rules: react/wrap-multilines.
```javascript
// bad
render() {
return <MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>;
}
// good
render() {
return (
<MyComponent className="long body" foo="bar">
<MyChild />
</MyComponent>
);
}
// good, 當只有一行
render() {
const body = <div>hello</div>;
return <MyComponent>{body}</MyComponent>;
}
```
- 沒有子標籤時總是使用自身結尾標籤。
eslint rules: react/self-closing-comp.
```javascript
// bad
<Foo className="stuff"></Foo>
// good
<Foo className="stuff" />
```
- 如果你的元件擁有多行屬性,結尾標籤請放在新的一行。
eslint rules: react/jsx-closing-bracket-location.
```javascript
// bad
<Foo
bar="bar"
baz="baz" />
// good
<Foo
bar="bar"
baz="baz"
/>
```
- Bind event handlers for the render method in the constructor.
Why? A bind call in a the render path create a brand new function on every single render.
eslint rules: react/jsx-no-bind.
```javascript
// bad
class extends React.Component {
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv.bind(this)} />
}
}
// good
class extends React.Component {
constructor(props) {
super(props);
this.onClickDiv = this.onClickDiv.bind(this);
}
onClickDiv() {
// do stuff
}
render() {
return <div onClick={this.onClickDiv} />
}
}
```
-
React 元件的內部方法不要使用底線當作前綴。
// bad React.createClass({ _onClickSubmit() { // do stuff }, // other stuff }); // good class extends React.Component { onClickSubmit() { // do stuff } // other stuff }
class extends React.Component的排序:
constructor- optional
staticmethods getChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmount- clickHandlers or eventHandlers like
onClickSubmit()oronChangeDescription() - getter methods for
renderlikegetSelectReason()orgetFooterContent() - Optional render methods like
renderNavigation()orrenderProfilePicture() render
-
How to define
propTypes,defaultProps,contextTypes, etc...import React, { PropTypes } from 'react'; const propTypes = { id: PropTypes.number.isRequired, url: PropTypes.string.isRequired, text: PropTypes.string, }; const defaultProps = { text: 'Hello World', }; class Link extends React.Component { static methodsAreOk() { return true; } render() { return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a> } } Link.propTypes = propTypes; Link.defaultProps = defaultProps; export default Link;
-
React.createClass的排序:
displayNamepropTypescontextTypeschildContextTypesmixinsstaticsdefaultPropsgetDefaultPropsgetInitialStategetChildContextcomponentWillMountcomponentDidMountcomponentWillReceivePropsshouldComponentUpdatecomponentWillUpdatecomponentDidUpdatecomponentWillUnmount- clickHandlers or eventHandlers like
onClickSubmit()oronChangeDescription() - getter methods for
renderlikegetSelectReason()orgetFooterContent() - Optional render methods like
renderNavigation()orrenderProfilePicture() render
eslint rules: react/sort-comp.
- Do not use
isMounted.
Why?
isMountedis an anti-pattern, is not available when using ES6 classes, and is on its way to being officially deprecated.
eslint rules: react/no-is-mounted.