|
5 | 5 | ## Table of Contents |
6 | 6 |
|
7 | 7 | 1. [Basic Rules](#basic-rules) |
| 8 | + 1. [Class vs `React.createClass`](#class-vs-reactcreateclass) |
8 | 9 | 1. [Naming](#naming) |
9 | 10 | 1. [Declaration](#declaration) |
10 | 11 | 1. [Alignment](#alignment) |
|
23 | 24 | - Always use JSX syntax. |
24 | 25 | - Do not use `React.createElement` unless you're initializing the app from a file that is not JSX. |
25 | 26 |
|
26 | | -## Class vs React.createClass |
| 27 | +## Class vs `React.createClass` |
27 | 28 |
|
28 | | - - Use class extends React.Component unless you have a very good reason to use mixins. |
| 29 | + - Use `class extends React.Component` unless you have a very good reason to use mixins. |
29 | 30 |
|
30 | 31 | eslint rules: [`react/prefer-es6-class`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-es6-class.md). |
31 | 32 |
|
32 | | - ```javascript |
33 | | - // bad |
34 | | - const Listing = React.createClass({ |
35 | | - render() { |
36 | | - return <div />; |
37 | | - } |
38 | | - }); |
| 33 | + ```javascript |
| 34 | + // bad |
| 35 | + const Listing = React.createClass({ |
| 36 | + render() { |
| 37 | + return <div />; |
| 38 | + } |
| 39 | + }); |
39 | 40 |
|
40 | | - // good |
41 | | - class Listing extends React.Component { |
42 | | - render() { |
43 | | - return <div />; |
| 41 | + // good |
| 42 | + class Listing extends React.Component { |
| 43 | + render() { |
| 44 | + return <div />; |
| 45 | + } |
44 | 46 | } |
45 | | - } |
46 | | - ``` |
| 47 | + ``` |
47 | 48 |
|
48 | 49 | ## Naming |
49 | 50 |
|
50 | 51 | - **Extensions**: Use `.jsx` extension for React components. |
51 | 52 | - **Filename**: Use PascalCase for filenames. E.g., `ReservationCard.jsx`. |
52 | 53 | - **Reference Naming**: Use PascalCase for React components and camelCase for their instances. |
53 | 54 |
|
54 | | - eslint rules: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md). |
| 55 | + eslint rules: [`react/jsx-pascal-case`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-pascal-case.md). |
55 | 56 |
|
56 | 57 | ```javascript |
57 | 58 | // bad |
|
67 | 68 | const reservationItem = <ReservationCard />; |
68 | 69 | ``` |
69 | 70 |
|
70 | | - **Component Naming**: Use the filename as the component name. For example, `ReservationCard.jsx` should have a reference name of `ReservationCard`. However, for root components of a directory, use `index.jsx` as the filename and use the directory name as the component name: |
| 71 | + **Component Naming**: Use the filename as the component name. For example, `ReservationCard.jsx` should have a reference name of `ReservationCard`. However, for root components of a directory, use `index.jsx` as the filename and use the directory name as the component name: |
| 72 | + |
71 | 73 | ```javascript |
72 | 74 | // bad |
73 | 75 | const Footer = require('./Footer/Footer.jsx') |
|
79 | 81 | const Footer = require('./Footer') |
80 | 82 | ``` |
81 | 83 |
|
82 | | - |
83 | 84 | ## Declaration |
84 | | - - Do not use displayName for naming components. Instead, name the component by reference. |
| 85 | + |
| 86 | + - Do not use `displayName` for naming components. Instead, name the component by reference. |
85 | 87 |
|
86 | 88 | ```javascript |
87 | 89 | // bad |
|
96 | 98 | ``` |
97 | 99 |
|
98 | 100 | ## Alignment |
| 101 | + |
99 | 102 | - Follow these alignment styles for JSX syntax |
100 | 103 |
|
101 | 104 | eslint rules: [`react/jsx-closing-bracket-location`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-closing-bracket-location.md). |
|
124 | 127 | ``` |
125 | 128 |
|
126 | 129 | ## Quotes |
| 130 | + |
127 | 131 | - Always use double quotes (`"`) for JSX attributes, but single quotes for all other JS. |
128 | 132 |
|
129 | 133 | > Why? JSX attributes [can't contain escaped quotes](http://eslint.org/docs/rules/jsx-quotes), so double quotes make conjunctions like `"don't"` easier to type. |
|
146 | 150 | ``` |
147 | 151 |
|
148 | 152 | ## Spacing |
| 153 | +
|
149 | 154 | - Always include a single space in your self-closing tag. |
| 155 | +
|
150 | 156 | ```javascript |
151 | 157 | // bad |
152 | 158 | <Foo/> |
|
163 | 169 | ``` |
164 | 170 |
|
165 | 171 | ## Props |
| 172 | +
|
166 | 173 | - Always use camelCase for prop names. |
| 174 | +
|
167 | 175 | ```javascript |
168 | 176 | // bad |
169 | 177 | <Foo |
|
179 | 187 | ``` |
180 | 188 |
|
181 | 189 | ## Parentheses |
| 190 | +
|
182 | 191 | - Wrap JSX tags in parentheses when they span more than one line. |
183 | 192 |
|
184 | 193 | eslint rules: [`react/wrap-multilines`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/wrap-multilines.md). |
|
208 | 217 | ``` |
209 | 218 |
|
210 | 219 | ## Tags |
| 220 | +
|
211 | 221 | - Always self-close tags that have no children. |
212 | 222 |
|
213 | 223 | eslint rules: [`react/self-closing-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/self-closing-comp.md). |
|
238 | 248 | ``` |
239 | 249 |
|
240 | 250 | ## Methods |
| 251 | +
|
241 | 252 | - Do not use underscore prefix for internal methods of a React component. |
| 253 | +
|
242 | 254 | ```javascript |
243 | 255 | // bad |
244 | 256 | React.createClass({ |
|
261 | 273 |
|
262 | 274 | ## Ordering |
263 | 275 |
|
264 | | - - Ordering for class extends React.Component: |
265 | | -
|
266 | | - 1. constructor |
267 | | - 1. optional static methods |
268 | | - 1. getChildContext |
269 | | - 1. componentWillMount |
270 | | - 1. componentDidMount |
271 | | - 1. componentWillReceiveProps |
272 | | - 1. shouldComponentUpdate |
273 | | - 1. componentWillUpdate |
274 | | - 1. componentDidUpdate |
275 | | - 1. componentWillUnmount |
276 | | - 1. *clickHandlers or eventHandlers* like onClickSubmit() or onChangeDescription() |
277 | | - 1. *getter methods for render* like getSelectReason() or getFooterContent() |
278 | | - 1. *Optional render methods* like renderNavigation() or renderProfilePicture() |
279 | | - 1. render |
280 | | -
|
281 | | - - How to define propTypes, defaultProps, contextTypes, etc... |
282 | | -
|
283 | | - ```javascript |
284 | | - import React, { PropTypes } from 'react'; |
285 | | -
|
286 | | - const propTypes = { |
287 | | - id: PropTypes.number.isRequired, |
288 | | - url: PropTypes.string.isRequired, |
289 | | - text: PropTypes.string, |
290 | | - }; |
291 | | -
|
292 | | - const defaultProps = { |
293 | | - text: 'Hello World', |
294 | | - }; |
295 | | -
|
296 | | - class Link extends React.Component { |
297 | | - static methodsAreOk() { |
298 | | - return true; |
299 | | - } |
| 276 | + - Ordering for `class extends React.Component`: |
| 277 | +
|
| 278 | + 1. `constructor` |
| 279 | + 1. optional `static` methods |
| 280 | + 1. `getChildContext` |
| 281 | + 1. `componentWillMount` |
| 282 | + 1. `componentDidMount` |
| 283 | + 1. `componentWillReceiveProps` |
| 284 | + 1. `shouldComponentUpdate` |
| 285 | + 1. `componentWillUpdate` |
| 286 | + 1. `componentDidUpdate` |
| 287 | + 1. `componentWillUnmount` |
| 288 | + 1. *clickHandlers or eventHandlers* like `onClickSubmit()` or `onChangeDescription()` |
| 289 | + 1. *getter methods for `render`* like `getSelectReason() or `getFooterContent()` |
| 290 | + 1. *Optional render methods* like `renderNavigation()` or `renderProfilePicture()` |
| 291 | + 1. `render` |
| 292 | +
|
| 293 | + - How to define `propTypes`, `defaultProps`, `contextTypes`, etc... |
300 | 294 |
|
301 | | - render() { |
302 | | - return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a> |
| 295 | + ```javascript |
| 296 | + import React, { PropTypes } from 'react'; |
| 297 | +
|
| 298 | + const propTypes = { |
| 299 | + id: PropTypes.number.isRequired, |
| 300 | + url: PropTypes.string.isRequired, |
| 301 | + text: PropTypes.string, |
| 302 | + }; |
| 303 | +
|
| 304 | + const defaultProps = { |
| 305 | + text: 'Hello World', |
| 306 | + }; |
| 307 | +
|
| 308 | + class Link extends React.Component { |
| 309 | + static methodsAreOk() { |
| 310 | + return true; |
| 311 | + } |
| 312 | +
|
| 313 | + render() { |
| 314 | + return <a href={this.props.url} data-id={this.props.id}>{this.props.text}</a> |
| 315 | + } |
303 | 316 | } |
304 | | - } |
305 | | -
|
306 | | - Link.propTypes = propTypes; |
307 | | - Link.defaultProps = defaultProps; |
308 | | -
|
309 | | - export default Link; |
310 | | - ``` |
311 | | -
|
312 | | - - Ordering for React.createClass: |
313 | | -
|
314 | | - 1. displayName |
315 | | - 1. propTypes |
316 | | - 1. contextTypes |
317 | | - 1. childContextTypes |
318 | | - 1. mixins |
319 | | - 1. statics |
320 | | - 1. defaultProps |
321 | | - 1. getDefaultProps |
322 | | - 1. getInitialState |
323 | | - 1. getChildContext |
324 | | - 1. componentWillMount |
325 | | - 1. componentDidMount |
326 | | - 1. componentWillReceiveProps |
327 | | - 1. shouldComponentUpdate |
328 | | - 1. componentWillUpdate |
329 | | - 1. componentDidUpdate |
330 | | - 1. componentWillUnmount |
331 | | - 1. *clickHandlers or eventHandlers* like onClickSubmit() or onChangeDescription() |
332 | | - 1. *getter methods for render* like getSelectReason() or getFooterContent() |
333 | | - 1. *Optional render methods* like renderNavigation() or renderProfilePicture() |
334 | | - 1. render |
| 317 | +
|
| 318 | + Link.propTypes = propTypes; |
| 319 | + Link.defaultProps = defaultProps; |
| 320 | +
|
| 321 | + export default Link; |
| 322 | + ``` |
| 323 | +
|
| 324 | + - Ordering for `React.createClass`: |
| 325 | +
|
| 326 | + 1. `displayName` |
| 327 | + 1. `propTypes` |
| 328 | + 1. `contextTypes` |
| 329 | + 1. `childContextTypes` |
| 330 | + 1. `mixins` |
| 331 | + 1. `statics` |
| 332 | + 1. `defaultProps` |
| 333 | + 1. `getDefaultProps` |
| 334 | + 1. `getInitialState` |
| 335 | + 1. `getChildContext` |
| 336 | + 1. `componentWillMount` |
| 337 | + 1. `componentDidMount` |
| 338 | + 1. `componentWillReceiveProps` |
| 339 | + 1. `shouldComponentUpdate` |
| 340 | + 1. `componentWillUpdate` |
| 341 | + 1. `componentDidUpdate` |
| 342 | + 1. `componentWillUnmount` |
| 343 | + 1. *clickHandlers or eventHandlers* like `onClickSubmit()` or `onChangeDescription()` |
| 344 | + 1. *getter methods for `render`* like `getSelectReason()` or `getFooterContent()` |
| 345 | + 1. *Optional render methods* like `renderNavigation()` or `renderProfilePicture()` |
| 346 | + 1. `render` |
335 | 347 |
|
336 | 348 | eslint rules: [`react/sort-comp`](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md). |
337 | 349 |
|
338 | 350 | ## `isMounted` |
339 | 351 |
|
340 | | - [`isMounted` is an anti-pattern][anti-pattern], is not available when using ES6 classes, and is on its way to being officially deprecated. Its use should be avoided. |
| 352 | + - Do not use `isMounted`. |
| 353 | +
|
| 354 | + > Why? [`isMounted` is an anti-pattern][anti-pattern], is not available when using ES6 classes, and is on its way to being officially deprecated. |
341 | 355 |
|
342 | 356 | [anti-pattern]: https://facebook.github.io/react/blog/2015/12/16/ismounted-antipattern.html |
343 | 357 |
|
|
0 commit comments