基本
每個文件只寫一個組件,但是多個無狀態(tài)組件可以放在單個文件中。
組件
- 【強(qiáng)制】有內(nèi)部狀態(tài),方法或者是要對外暴露ref的組件,使用ES6 Class寫法。
// bad
const Listing = React.createClass({
// ...
render() {
return <div>{this.state.hello}</div>;
}
});
// good
class Listing extends React.Component {
// ...
render() {
return <div>{this.state.hello}</div>;
}
}
- 沒有內(nèi)部狀態(tài),方法或者是無需對外暴露ref的組件,使用函數(shù)寫法。
// bad
class Listing extends React.Component {
render() {
return <div>{this.props.hello}</div>;
}
}
// good
const Listing = ({ hello }) => (
<div>{hello}</div>
);
PropTypes/DefaultProps
- 有內(nèi)部狀態(tài),方法或者是要對外暴露ref的組件,使用ES7類靜態(tài)屬性提案寫法。
class Button extends Component {
static propTypes = {
size: React.PropTypes.oneOf(['large', 'normal', 'small']),
shape: React.PropTypes.oneOf(['default', 'primary', 'ghost'])
disabled: React.PropTypes.bool
};
static defaultProps = {
size: 'normal',
shape: 'default',
disabled: false
};
render() {
// ....
}
}
- 沒有內(nèi)部狀態(tài),方法或者無需對外暴露ref的組件,使用類靜態(tài)屬性寫法。
const HelloMessage = ({ name }) => {
return <div>Hello {name}</div>;
};
HelloMessage.propTypes = {
name: React.PropTypes.string
};
HelloMessage.defaultProps = {
name: 'vic'
};
- PropTypes必須。
State
- 使用ES7實(shí)例屬性提案聲明寫法或者構(gòu)造函數(shù)聲明寫法,后者適合需要進(jìn)行一定計(jì)算后才能初始化state的情況
class Some extends Component {
state = {
foo: 'bar'
};
// ....
}
class Some extends Component {
constructor(props) {
super(props);
this.state = {
foo: 'bar'
};
}
// ....
}
- 【建議】不建議對this.state進(jìn)行賦值。
// bad
this.state.name = this.props.name.toUpperCase();
// good
this.setState({
name: this.props.name.toUpperCase();
});
DisplayName
- 【建議】為了調(diào)試方便,建議在組件最上面寫displayName。
// good
class Some extends Component {
static displayName = 'Some';
// ....
}
命名
- 【強(qiáng)制】擴(kuò)展名: React組件文件使用.jsx擴(kuò)展名。
- 文件名: 文件名使用駝峰式命名,首字母大寫,如ReservationCard.jsx。
- 引用命名: React組件名使用駝峰式命名,首字母大寫,實(shí)例名也使用駝峰式命名,但首字母小寫。
// bad
import reservationCard from './ReservationCard';
// good
import ReservationCard from './ReservationCard';
// bad
const ReservationItem = <ReservationCard />;
// good
const reservationItem = <ReservationCard />;
引號
- 對于JSX屬性值總是使用雙引號", 其他均使用單引號'。
// bad
<Foo bar='bar' />
// good
<Foo bar="bar" />
// bad
<Foo style={{ left: "20px" }} />
// good
<Foo style={{ left: '20px' }} />
空格
- 【建議】總是在自閉合的標(biāo)簽/>前加一個空格。
// bad
<Foo/>
// very bad
<Foo />
// good
<Foo />
- 【建議】不要在JSX{}引用括號里兩邊加空格。
// bad
<Foo bar={ baz } />
// good
<Foo bar={baz} />
- 【建議】不要在JSX props屬性=兩邊加空格。
// bad
<Hello name = {firstname} />;
// good
<Hello name={firstname} />;
屬性
- 【強(qiáng)制】JSX屬性名總是使用駝峰式風(fēng)格。
// bad
<Foo UserName="hello" phone_number={12345678} />
// good
<Foo userName="hello" phoneNumber={12345678} />
- 【建議】如果屬性值為true, 可以直接省略。
// bad
<Foo hidden={true} />
// good
<Foo hidden />
- 強(qiáng)制】數(shù)組中或者遍歷中輸出相同的React組件,屬性key必需。
// bad
[<Hello />, <Hello />, <Hello />];
data.map(x => <Hello>x</Hello>);
// good
[<Hello key="first" />, <Hello key="second" />, <Hello key="third" />];
data.map((x, i) => <Hello key={i}>x</Hello>);
- 【強(qiáng)制】class以及for等關(guān)鍵字不允許作為屬性名。
// bad
<div class="hello">Hello World</div>;
// good
<div className="hello">Hello World</div>;
- 【強(qiáng)制】屬性名不允許重復(fù)聲明。
// bad
<Hello name="John" name="John" />;
// good
<Hello firstname="John" lastname="Doe" />;
Refs
- 【強(qiáng)制】總是在Refs里使用回調(diào)函數(shù)。
// bad
<Foo
ref="myRef"
/>
// good
<Foo
ref={ref => { this.myRef = ref; }}
/>
括號
- 【建議】將多行的JSX標(biāo)簽寫在()里,單行可以省略()。
// 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>;
}
標(biāo)簽
- 對于沒有子元素的標(biāo)簽來說總是閉合的。
// bad
<Foo className="stuff"></Foo>
// good
<Foo className="stuff" />
方法
- render方法必須有值返回。
// bad
render() {
(<div />);
}
// good
render() {
return (<div />);
}
- 【建議】按照以下順序排序內(nèi)部方法。
1. static methods and properties
2. lifecycle methods: displayName, propTypes, contextTypes, childContextTypes, mixins, statics,defaultProps, constructor, getDefaultProps, getInitialState, state, getChildContext, componentWillMount, componentDidMount, componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, componentDidUpdate, componentWillUnmount (in this order).
3. custom methods
4. render method`
- 【建議】不要在componentDidMount以及componentDidUpdate中調(diào)用setState,除非是在綁定的回調(diào)函數(shù)中設(shè)置State。
// bad
class Hello extends Component {
componentDidMount() {
this.setState({
name: this.props.name.toUpperCase()
});
}
render() {
return <div>Hello {this.state.name}</div>;
}
}
// good
class Hello extends Component {
componentDidMount() {
this.onMount(newName => {
this.setState({
name: newName
});
});
}
render() {
return <div>Hello {this.state.name}</div>;
}
}
- 【建議】使用箭頭函數(shù)來獲取本地變量。
function ItemList(props) {
return (
<ul>
{props.items.map((item, index) => (
<Item
key={item.key}
onClick={() => doSomethingWith(item.name, index)}
/>
))}
</ul>
);
}
- 【建議】當(dāng)在render()里使用事件處理方法時,提前在構(gòu)造函數(shù)里把this綁定上去。
解釋:為什么?在每次render過程中, 再調(diào)用bind都會新建一個新的函數(shù),浪費(fèi)資源。
// 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模塊中,不要給所謂的私有函數(shù)添加_前綴,本質(zhì)上它并不是私有的。
解釋:_下劃線前綴在某些語言中通常被用來表示私有變量或者函數(shù)。但是不像其他的一些語言,在JS中沒有原生支持所謂的私有變量,所有的變量函數(shù)都是共有的。盡管你的意圖是使它私有化,在之前加上下劃線并不會使這些變量私有化,并且所有的屬性(包括有下劃線前綴及沒有前綴的)都應(yīng)該被視為是共有的。
// bad
React.createClass({
_onClickSubmit() {
// do stuff
},
// other stuff
});
// good
class extends React.Component {
onClickSubmit() {
// do stuff
}
// other stuff
}