基本規則
- 每個文件只包含一個React組件。
- 但是,每個文件允許多個無狀態或純組件。
- 始終使用JSX語法。
React.createElement
除非您從不是JSX的文件初始化應用程序,否則請勿使用。
Class vs React.createClass
vs stateless
-
If you have internal state and/or refs, prefer
class extends React.Component
overReact.createClass
.// 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>; } }
And if you don’t have state or refs, prefer normal functions (not arrow functions) over classes:
// bad class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // bad (relying on function name inference is discouraged) const Listing = ({ hello }) => ( <div>{hello}</div> ); // good function Listing({ hello }) { return <div>{hello}</div>; }
命名
-
擴展:使用
.jsx
React組件的擴展。 -
文件名:使用PascalCase作爲文件名。例如,
ReservationCard.jsx
。 -
參考命名:對其實例使用PascalCase用於React組件和camelCase。
-
// 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
生成組件的組合。例如,高次成分withFoo()
,通過當組件Bar
應該產生一個組分與displayName
的withFoo(Bar)
。// bad export default function withFoo(WrappedComponent) { return function WithFoo(props) { return <WrappedComponent {...props} foo />; } } // good export default function withFoo(WrappedComponent) { function WithFoo(props) { return <WrappedComponent {...props} foo />; } const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component'; WithFoo.displayName = `withFoo(${wrappedComponentName})`; return WithFoo; }
-
道具命名:避免將DOM組件道具名稱用於不同目的。
// bad <MyComponent style="fancy" /> // bad <MyComponent className="fancy" /> // good <MyComponent variant="fancy" />
宣言
-
不要
displayName
用於命名組件。而是通過引用命名組件。
-
// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
對準
-
遵循JSX語法的這些對齊樣式。
-
// bad <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // good <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // if props fit in one line then keep it on the same line <Foo bar="bar" /> // children get indented normally <Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo> // bad {showButton && <Button /> } // bad { showButton && <Button /> } // good {showButton && ( <Button /> )} // good {showButton && <Button />}
行情
-
始終
"
對JSX屬性使用雙引號(),但'
對所有其他JS使用單引號()。 -
// 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 />
-
不要用空格填充JSX花括號。
// bad <Foo bar={ baz } /> // good <Foo bar={baz} />
道具
-
始終使用camelCase作爲道具名稱。
// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
-
明確時,忽略道具的值
true。
// bad <Foo hidden={true} /> // good <Foo hidden /> // good <Foo hidden />
-
始終
alt
在<img>
標籤上包含道具。如果圖像是表現形式,alt
則可以是空字符串或<img>
必須具有的字符串role="presentation"
。// bad <img src="hello.jpg" /> // good <img src="hello.jpg" alt="Me waving hello" /> // good <img src="hello.jpg" alt="" /> // good <img src="hello.jpg" role="presentation" />
-
不要在
<img>
alt
道具中使用“圖像”,“照片”或“圖片”等字樣。// bad <img src="hello.jpg" alt="Picture of me waving hello" /> // good <img src="hello.jpg" alt="Me waving hello" />
-
Use only valid, non-abstract ARIA roles. eslint:
jsx-a11y/aria-role
// bad - not an ARIA role <div role="datepicker" /> // bad - abstract ARIA role <div role="range" /> // good <div role="button" />
-
僅使用有效的非抽象ARIA角色。
// bad <div accessKey="h" /> // good <div />
- 不要
accessKey
在元素上使用。
避免使用數組索引作爲key
prop,更喜歡穩定的ID
// bad {todos.map((todo, index) => <Todo {...todo} key={index} /> )} // good {todos.map(todo => ( <Todo {...todo} key={todo.id} /> ))}
- 始終爲所有不需要的道具定義顯式defaultProp。
// bad function SFC({ foo, bar, children }) { return <div>{foo}{bar}{children}</div>; } SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, children: PropTypes.node, }; // good function SFC({ foo, bar, children }) { return <div>{foo}{bar}{children}</div>; } SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, children: PropTypes.node, }; SFC.defaultProps = { bar: '', children: null, };
- 謹慎使用傳播道具。
例外:
- 代理道具並提升propTypes的HOC
function HOC(WrappedComponent) { return class Proxy extends React.Component { Proxy.propTypes = { text: PropTypes.string, isLoading: PropTypes.bool }; render() { return <WrappedComponent {...this.props} /> } } }
- 使用已知的顯式道具傳播對象。當使用Mocha的beforeEach構造測試React組件時,這可能特別有用。
export default function Foo { const props = { text: '', isPublished: false } return (<div {...props} />); }
使用注意事項:儘可能過濾掉不必要的道具。另外,使用prop-types-exact來幫助防止錯誤。
// bad render() { const { irrelevantProp, ...relevantProps } = this.props; return <WrappedComponent {...this.props} /> } // good render() { const { irrelevantProp, ...relevantProps } = this.props; return <WrappedComponent {...relevantProps} /> }
參考文獻
-
始終使用ref回調。
// bad <Foo ref="myRef" /> // good <Foo ref={(ref) => { this.myRef = ref; }} />
括弧
-
當它們跨越多行時,在括號中包裝JSX標記。
-
// bad render() { return <MyComponent variant="long body" foo="bar"> <MyChild /> </MyComponent>; } // good render() { return ( <MyComponent variant="long body" foo="bar"> <MyChild /> </MyComponent> ); } // good, when single line render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
標籤
-
總是自我關閉沒有孩子的標籤
-
// bad <Foo variant="stuff"></Foo> // good <Foo variant="stuff" />
-
如果組件具有多行屬性,請在新行上關閉其標記。
// bad <Foo bar="bar" baz="baz" /> // good <Foo bar="bar" baz="baz" />
方法
-
使用箭頭函數關閉局部變量。
-
function ItemList(props) { return ( <ul> {props.items.map((item, index) => ( <Item key={item.key} onClick={() => doSomethingWith(item.name, index)} /> ))} </ul> ); }
-
綁定構造函數中render方法的事件處理程序。
// 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 }
-
請務必在
render
方法中返回一個值。// bad render() { (<div />); } // good render() { return (<div />); }
-
如何定義
propTypes
,defaultProps
,contextTypes
, etc...import React from 'react'; import PropTypes from 'prop-types'; 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開發時遵循的一些語法規範。如有不足之處,歡迎大家給出建議!