React ⚡️
Formatting
- Use soft-tabs with a two space indent.
- Limit each line of code to fewer than 130 characters.
- End each file with a newline.
Naming
- Use
jsx
extensions for components, screens etc. -
Use
PascalCase
for files with thejsx
extension:components/ ├── Button/ │ ├── index.jsx screens/ ├── Home/ │ ├── index.jsx
index.jsx
is the only exception to this rule as it represents the folder root. This filename can also be omitted in import statements:import Button from '../Button/'
. -
Use
camelCase
for all other files with ajs
extension:lib/ ├── requestManager.js helpers/ ├── userHelper.js
-
Use
camelCase
for variables and functions:// Bad let form_params = {}; function FetchParams() { return {}; } // Good let formParams = {}; function fetchParams() { return {}; }
-
Use
PascalCase
for classes:// Bad class product_form {} class productForm {} // Good class ProductForm {}
-
Use
SCREAMING_SNAKE_CASE
for constants:// Bad const fetchLimit = 25; // Good const FETCH_LIMIT = 25;
This formatting is somewhat inherited from Ruby but is widely accepted in the JS community.
-
Use
camelCase
for prop names andPascalCase
if the prop value is a React component:// Bad <Foo UserName='hello' phone_number={ 12345678 } /> // Good <Foo userName='hello' phoneNumber={ 12345678 } Component={ SomeComponent } />
Props
-
Omit the value of the prop when it is explicitly
true
:// Bad <Foo hidden={true} /> // Good <Foo hidden />
-
Always include an
alt
prop ontags. If the image is presentational, alt can be an empty string or the
must have 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' />
-
Avoid using an array index as key prop, prefer a stable ID:
// Bad { todos.map((todo, index) => <Todo {...todo} key={index} /> ) } // Good { todos.map(todo => ( <Todo {...todo} key={todo.id} /> )) }
Tags
-
For single components (having no children), always use self-close tags.
// Bad <Foo variant="noChildren"></Foo> // Good <Foo variant="noChildren" />
-
For component with multi-line properties, close the tag on a new line
// Bad <Foo bar="bar" foo="foo" /> // Good <Foo bar="bar" foo="foo" />
Functions
-
Use arrow functions to close over local variables.
function TaskList(props) { return ( <ul> {props.tasks.map((task, index) => ( <Item key={task.key} onClick={() => someFunc(task.name, index)} /> ))} </ul> ); }
-
In the constructor, Bind event handlers for the render method, Otherwise it creates a whole new function on every single render and reduces performance.
// Bad class extends React.Component { onClickDiv() { .... } render() { return <div onClick={this.onClickDiv.bind(this)} />; } } // Good class extends React.Component { constructor(props) { super(props); this.onClickDiv = this.onClickDiv.bind(this); } onClickDiv() { .... } render() { return <div onClick={this.onClickDiv} />; } }
-
Be sure to return a value in
render
methods.// bad render() { (<div />); } // good render() { return (<div />); }
Project Structure
After working on several React
projects, we settled down on the following file organization (this structure is closed to the general JS application structure):
adapters/
├── product.js
components/
├── Product/
│ ├── index.jsx
├── ProductList/
│ ├── index.jsx
constants/
├── product.js
contexts/
├── auth.js
helpers/
├── formatProductDescription.js
reducers/
├── product.js
screens/
├── ProductDetails/
│ ├── index.jsx
services/
├── googleMap.js
tests/
├── components/
│ ├── Product/
│ │ ├── index.test.js
-
adapters/
: the classes in charge of making network and/or async tasks. We usually create one file per API resource. -
components/
: the stateless and reusableReact
components. -
constants/
: thereducers
types under this directory. The organization of this directory should match the folder structure of thereducers
. -
contexts
: creating contexts and context providers. -
helpers/
: Any utilities used in the project. -
reducers/
: theRedux
reducers. The organization of this directory should match the folder structure ofcontexts
andconstants
. -
screens/
: the page specific components which are in charge of rendering all other stateless components to build any specific page. -
services/
: the service classes used in the project. By definition, these classes should encapsulate one single process of the app. -
tests
: Unit tests for components, screens, helpers etc.
Components / Screens
Use a folder structure with an index file (and other files when required):
// Bad
components/
├── Button.jsx
screens/
├── Product.jsx
// Good
components/
├── Button/
│ ├── index.jsx
screens/
├── ProductDetails/
│ ├── index.jsx
This is both a future-proof measure and a mean to break down components into small meaningful modules:
components/
├── Button/
│ ├── index.jsx
│ ├── loading.jsx
│ ├── propTypes.js
screens/
├── ProductDetails/
│ ├── index.jsx
│ ├── header.jsx
│ ├── gallery.jsx
Component Props
React PropTypes
are a critical part of creating re-usable components with a clear API.
-
Use the right
PropType
that matches the expected data type for each prop:Button.propTypes = { /** * Holds the text to display in the button. **/ text: PropTypes.string, /** * Disabled state **/ disabled: PropTypes.bool, /** * Click event handler. **/ onClick: PropTypes.func, /** * Select the style type. **/ styleType: PropTypes.oneOf(['default', 'primary', 'secondary']) };
-
Define which
prop
is required:Button.propTypes = { /** * Holds the text to display in the button. **/ text: PropTypes.string.isRequired, /** * Disabled state **/ disabled: PropTypes.bool };
-
Use
PropTypes.shape
to define complex props:/** * Available action creators. **/ actions: PropTypes.shape({ /** * When a ticket is selected. **/ pickTicket: PropTypes.func.isRequired, /** * When a ticket is unselected. **/ unpickTicket: PropTypes.func.isRequired }).isRequired /** * Holds the search store. * */ search: PropTypes.shape({ /** * Holds the origin city. **/ origin: PropTypes.string.isRequired, /** * Holds the destination city. **/ destination: PPropTypes.string.isRequired }).isRequired
The definition of PropTypes
allows for complex type structure between components:
components/
├── Product/
│ ├── index.jsx
│ ├── propTypes.js
├── Feed/
│ ├── index.jsx
│ ├── propTypes.js
In Feed/propTypes.js
:
import PropTypes from 'prop-types';
import productPropType from '../Product/propTypes';
export const feedPropType = PropTypes.shape({
products: PropTypes.arrayOf(productPropType).isRequired,
...
});
Tests
The tests
folder should have unit tests for the application. The folder structure of the tests should be
similar to the structure of the application. For example if we have a product.js
file in below structure
components/
├── Product/
│ ├── product.js
then the structure in tests
folder should be
tests/
├── components/
│ ├── Product/
│ │ ├── product.test.js
Many of the React formatting conventions derived from the Javascript conventions.