Come from Chinese Coding Specification for Airbnb React/JSX
Airbnb React/JSX Coding Specification
One of the most reasonable React/JSX coding specifications
Content directory
Basic Rules Basic Specification
-
Each file only writes one module.
But there are many. Stateless module It can be placed in a single file. eslint: react/no-multi-comp.
JSX grammar is recommended.
Do not use React.createElement unless you initialize your app from a non-JSX file.
Create module
Class vs React.createClass vs stateless
If your module has internal status or refs, it is recommended to use class extends React.Component instead of React.createClass unless you have good reasons to use these methods.
eslint: react/prefer-es6-class react/prefer-stateless-function
// 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>; } }
If your module is stateless or does not refer to `refs', it is recommended to use normal functions (non-arrow functions) instead of 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>; }
Naming
Extension: React module uses. jsx extension.
- File name: File name is named after Pascal. For example, ReservationCard.jsx.
- Reference naming: The React module name is Pascal naming, and the instance is camel naming. react/jsx-pascal-case
// bad import reservationCard from './ReservationCard'; // good import ReservationCard from './ReservationCard'; // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;
-
Module Naming: Modules use the same name as the current file name. For example, ReservationCard.jsx should contain a module named ReservationCard. However, if the entire folder is a module, use index.js as the entry file, and then use index.js or folder name directly as the module name:
// bad import Footer from './Footer/Footer'; // bad import Footer from './Footer/index'; // good import Footer from './Footer';
High-order module naming: For generating a new module, the module name displayName should be a combination of the high-order module name and the incoming module name. For example, the high-order module withFoo(), when passing in a Bar module, the generated module name displayName should be withFoo(Bar).
Why? A module's displayName may be used in developer tools or error messages, so having a value that clearly expresses this relationship can help us better understand what's happening in the module and better Debug.
// 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; }
Property naming: Avoid using DOM-related properties for other purposes.
Why? For attribute names such as style and className, we all default that they represent specific meanings, such as the style of the element and the name of the CSS class. Using these attributes to represent other meanings in your application will make your code harder to read, more difficult to maintain, and may cause bug s.
// bad <MyComponent style="fancy" /> // good <MyComponent variant="fancy" />
Declaration declaration module
-
Instead of using displayName to name React modules, use references to name modules, such as class names.
// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good export default class ReservationCard extends React.Component { }
Alignment code alignment
-
Follow the following JSX syntax indentation/format. eslint: react/jsx-closing-bracket-location
// bad <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // good, if you have multiple line attributes, create a new line to close the label <Foo superLongParam="bar" anotherSuperLongParam="baz" /> // If you can display it in one line, write it directly in one line <Foo bar="bar" /> // Subelements are indented in a conventional way <Foo superLongParam="bar" anotherSuperLongParam="baz" > <Quux /> </Foo>
Quotes Single or Double Quotes
Double quotation marks (") are always used for JSX attribute values, and single quotation marks ('). eslint: jsx-quotes
Why? HTML attributes also use double quotation marks, so JSX attributes follow this convention.
// bad <Foo bar='bar' /> // good <Foo bar="bar" /> // bad <Foo style={{ left: "20px" }} /> // good <Foo style={{ left: '20px' }} />
Spacing space
-
Always add a space before the auto-closing label. Normally, no line change is required. no-multi-spaces, react/jsx-space-before-closing
// bad <Foo/> // very bad <Foo /> // bad <Foo /> // good <Foo />
-
Do not add spaces to both sides of the parentheses in JSX {} reference. react/jsx-curly-spacing
// bad <Foo bar={ baz } /> // good <Foo bar={baz} />
Props attribute
-
JSX attribute names use camelCase in camel style.
// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
-
If the attribute value is true, it can be omitted directly.eslint: react/jsx-boolean-value
// bad <Foo hidden={true} /> // good <Foo hidden />
-
The < img > tag always adds an alt attribute. If the image is displayed in presentation (feel like a PPT display?), ALT can be empty, or < img > should contain role="presentation". eslint: jsx-a11y/img-has-alt
// 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" />
Don't use words such as "image", "photo" or "picture" in alt values, including image meanings. The same is true in Chinese. jsx-a11y/img-redundant-alt
Why? The screen reader has labeled the img tag as a picture, so there's no need to explain it in alt.
// bad <img src="hello.jpg" alt="Picture of me waving hello" /> // good <img src="hello.jpg" alt="Me waving hello" />
-
Use valid and correct aria role attribute values 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" />
Do not use the accessKey attribute on tags. eslint: jsx-a11y/no-access-key
Why? The inconsistency between keyboard shortcuts and keyboard commands caused by screen readers can lead to more complex reading.
// bad <div accessKey="h" /> // good <div />
-
Avoid using array index as the value of attribute key, recommend using unique ID..( Why?)
// bad {todos.map((todo, index) => <Todo {...todo} key={index} /> )} // good {todos.map(todo => ( <Todo {...todo} key={todo.id} /> ))}
For all non-essential attributes, defaultProps attributes are always defined manually.
Why? ProTypes can be used as documentation for modules, and declaring defaultProps means that people reading code do not need to assume some default values. More importantly, the declared default properties displayed allow your module to skip checking for attribute types.
// 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 }) { return <div>{foo}{bar}</div>; } SFC.propTypes = { foo: PropTypes.number.isRequired, bar: PropTypes.string, }; SFC.defaultProps = { bar: '', children: null, };
Refs
-
Always use callback functions in Refs.eslint: react/no-string-refs
// bad <Foo ref="myRef" /> // good <Foo ref={(ref) => { this.myRef = ref; }} />
Parentheses parentheses
-
Write multi-line JSX tags in (). eslint: react/wrap-multilines
// bad render() { return <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent>; } // good render() { return ( <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent> ); } // good, a single line can be unnecessary render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
Tags Tags
-
For tags without child elements, always close the tag by yourself. react/self-closing-comp
// bad <Foo className="stuff"></Foo> // good <Foo className="stuff" />
-
If the module has multiple line attributes, create a new line when closing the label. eslint: react/jsx-closing-bracket-location
// bad <Foo bar="bar" baz="baz" /> // good <Foo bar="bar" baz="baz" />
Methods function
-
Use arrow functions to get local variables.
function ItemList(props) { return ( <ul> {props.items.map((item, index) => ( <Item key={item.key} onClick={() => doSomethingWith(item.name, index)} /> ))} </ul> ); }
When using event handling in render(), bind this in the constructor ahead of time. react/jsx-no-bind
Why? In every render process, calling bind creates a new function, which wastes resources.
// 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} /> } }
In the React module, don't prefix so-called private functions, it's not private in nature.
Why? _ Underline prefixes are often used to represent private variables or functions in some languages. But unlike some other languages, there is no native support for so-called private variables in JS, and all variable functions are common. Although your intention is to privatize it, underlining before it does not privatize these variables, and all attributes (including those with and without prefixes) should be considered common. For more details, see Issue #1024 , and #490 .
// bad React.createClass({ _onClickSubmit() { // do stuff }, // other stuff }); // good class extends React.Component { onClickSubmit() { // do stuff } // other stuff }
-
In render methods, always ensure the return return value.eslint: react/require-render-return
// bad render() { (<div />); } // good render() { return (<div />); }
Ordering React module life cycle
class extends React.Component's life cycle function:
Optional static Method
Constructor constructor
GettChildContext Gets the child element content
Before rendering the component WillMount module
After rendering the component DidMount module
CompoonentWillReceiveProps module will accept new data
Should Component Update Judgement Module Needs No Rendering
The method above componentWillUpdate returns true, and the module will be rendered again
Completion of rendering for component DidUpdate module
The component WillUnmount module will be cleared from the DOM to do some cleaning tasks
Click the callback or event handler such as onClickSubmit() or onChangeDescription()
getter methods in render, such as getSelectReason() or getFooterContent()
Optional render methods such as renderNavigation() or renderProfilePicture()
render
render() Method
-
How to define
propTypes
,defaultProps
,contextTypes
, Wait for other attributes...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;
The life cycle function of React.createClass is slightly different from that of using class: eslint: react/sort-comp
displayName Setting Module Name
propTypes Sets the Type of Properties
contextTypes Set Context Types
childContextTypes sets the child element context type
Mixers add some mixins
statics
defaultProps
Set default property valuesgetDefaultProps
Get the default attribute valuegetInitialState
Or the initial stategetChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
clickHandlers or eventHandlers like onClickSubmit() or onChangeDescription()
getter methods for render like getSelectReason() or getFooterContent()
Optional render methods like renderNavigation() or renderProfilePicture()
render
isMounted
Stop using isMounted. eslint: react/no-is-mounted
Why? isMounted Anti-Human Design Patterns: () This method is not available in ES6 classes and will be deleted in future versions.