A mostly reasonable approach to React and JSX
- Only include one React component per file.
- Always use JSX syntax.
- Do not use
React.createElement
unless you're initializing the app from a file that is not JSX.
- Use class extends React.Component unless you have a very good reason to use mixins.
// bad
const Checkbox = React.createClass({
render() {
<div>
<input type="checkbox" checked={this.props.checked} />
</div>
}
});
// good
class Checkbox extends React.Component {
render() {
<div>
<input type="checkbox" checked={this.props.checked} />
</div>
}
}
// better (stateless functions, react 0.14 and up only)
// https://github.com/reactjs/react-future/blob/master/01%20-%20Core/03%20-%20Stateless%20Functions.js
const Checkbox = ({ checked = false }) => {
return (
<div>
<input type="checkbox" checked={checked} />
</div>
);
};
-
Extensions: Use
.jsx
extension for React components. -
Filename: Use PascalCase for filenames. E.g.,
ReservationCard.jsx
. -
Reference Naming: Use PascalCase for React components and camelCase for their instances:
// bad const reservationCard = require('./ReservationCard'); // good const ReservationCard = require('./ReservationCard'); // bad const ReservationItem = <ReservationCard />; // good const reservationItem = <ReservationCard />;
Component Naming: Use the filename as the component name. For example,
ReservationCard.jsx
should have a reference name ofReservationCard
. However, for root components of a directory, useindex.jsx
as the filename and use the directory name as the component name:// bad const Footer = require('./Footer/Footer.jsx') // bad const Footer = require('./Footer/index.jsx') // good const Footer = require('./Footer')
-
Do not use displayName for naming components. Instead, name the component by reference.
// bad export default React.createClass({ displayName: 'ReservationCard', // stuff goes here }); // good class ReservationCard extends React.Component { } export default ReservationCard;
-
Follow these alignment styles for JSX syntax
// 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" > <Spazz /> </Foo>
- Always use double quotes (
"
) for JSX attributes, but single quotes for all other JS.// bad <Foo bar='bar' /> // good <Foo bar="bar" /> // bad <Foo style={{ left: "20px" }} /> // good <Foo style={{ left: '20px' }} />
- Always include a single space in your self-closing tag.
// bad <Foo/> // very bad <Foo /> // bad <Foo /> // good <Foo />
- Always use camelCase for prop names.
// bad <Foo UserName="hello" phone_number={12345678} /> // good <Foo userName="hello" phoneNumber={12345678} />
- Wrap JSX tags in parentheses when they span more than one line:
/// bad render() { return <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent>; } // good render() { return ( <MyComponent className="long body" foo="bar"> <MyChild /> </MyComponent> ); } // good, when single line render() { const body = <div>hello</div>; return <MyComponent>{body}</MyComponent>; }
-
Always self-close tags that have no children.
// bad <Foo className="stuff"></Foo> // good <Foo className="stuff" />
-
If your component has multi-line properties, close its tag on a new line.
// bad <Foo bar="bar" baz="baz" /> // good <Foo bar="bar" baz="baz" />
- Do not use underscore prefix for internal methods of a React component.
// bad React.createClass({ _onClickSubmit() { // do stuff } // other stuff }); // good class extends React.Component { onClickSubmit() { // do stuff } // other stuff });
- Ordering for class extends React.Component:
- constructor
- optional static methods
- getChildContext
- 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
- How to define propTypes, defaultProps, contextTypes, etc...
import React, { Component, PropTypes } from 'react';
export const propTypes = {
id: PropTypes.number.isRequired,
url: PropTypes.string.isRequired,
text: PropTypes.string,
};
const defaultProps = {
text: 'Hello World',
};
class Link extends 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;
- Ordering for React.createClass:
- displayName
- propTypes
- contextTypes
- childContextTypes
- mixins
- statics
- defaultProps
- getDefaultProps
- getInitialState
- getChildContext
- 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