Airbnb React/JSX Style Guide
Uma abordagem para padronização de códigos usada pela AirBNB React e JSX, traducão feita com base nesse repositório
Índice
- Regras Básicas
- Class vs
React.createClass
vs stateless - Nomenclatura
- Declaration
- Indentação
- Aspas
- Espaçamento
- Props
- Refs
- Parenteses
- Tags
- Métodos (Methods)
- Prioridades
isMounted
Regras Básicas
-
Apenas um componente por arquivo.
- Contudo, múltiplos componentes são permitidos quando são dependentes um do outro e apenas 1 tem retorno Statefull ou Stateless são permitidos por arquivo. eslint:
react/no-multi-comp
.
function Hello(props) { return <div>Hello {props.name}</div>; } class HelloJohn extends React.Component { render() { return <Hello name="John" />; } } module.exports = HelloJohn;
- Contudo, múltiplos componentes são permitidos quando são dependentes um do outro e apenas 1 tem retorno Statefull ou Stateless são permitidos por arquivo. eslint:
-
Sempre use a sintaxe JSX.
-
Não use
React.createElement
a não ser que você estaja declarando a partir de um arquivo que não seja JSX.
Class
vs React.createClass
vs stateless
-
Se você tem State interno e/ou refs, opte por
class extends React.Component
ao invés deReact.createClass
a menos que você tenha uma boa razão para usar um mixins. eslint:react/prefer-es6-class
react/prefer-stateless-function
// ruim const Listing = React.createClass({ // ... render() { return <div>{this.state.hello}</div>; } }); // ideal class Listing extends React.Component { // ... render() { return <div>{this.state.hello}</div>; } }
E se você não tem
state
ourefs
, prefira funções normais ( não arrow functions ) sobre as classes:// ruim class Listing extends React.Component { render() { return <div>{this.props.hello}</div>; } } // ruim (relying on function name inference is discouraged) const Listing = ({ hello }) => ( <div>{hello}</div> ); // ideal function Listing({ hello }) { return <div>{hello}</div>; }
Nomenclatura
-
Extensão: Use a extensão
.jsx
para componentes React. -
Nome do arquivo: Use PascalCase para os arquivos. Ex.:
MeuComponente.jsx
. -
Referência de nomenclatura: Use PascalCase para componentes e camelCase para as instâncias. eslint:
react/jsx-pascal-case
// ruim import reservationCard from './ReservationCard'; // ideal import ReservationCard from './ReservationCard'; // ruim const ReservationItem = <ReservationCard />; // ideal const reservationItem = <ReservationCard />; //instância em camel e componente em Pascal
-
Nomeando componentes: Use o mesmo nome do componente. Ex.:
MeuComponente.jsx
tem um nome que referênciaMeuComponente
. No entanto, para os componentes de raiz de um diretório, useindex.jsx
como o nome do arquivo e usar o nome de diretório como o nome do componente:
-
App
├─┬ Footer
│ ├── index.jsx (O componente Footer está declarado na index)
│ ├── MeuComponente.jsx
│
├─┬ Header
│ ├── index.jsx (O componente Header está declarado na index)
│ │
│ ├─┬ Meta
│ │ ├── index.jsx (O componente Meta está declarado na index)
│ │
│ ├─┬ Menu.jsx
│ │ ├── index.jsx
│ │ ├── Item.jsx// ruim import Footer from './Footer/Footer'; // ruim import Footer from './Footer/index'; // ideal import Footer from './Footer';
Declaração
-
Não use
displayName
para nomear componentes. Em vez disso, o nome do componente por referência.// ruim export default React.createClass({ displayName: 'MeuComponente', // alguma coisa aqui. }); // ideal export default class MeuComponente extends React.Component { // todo }
Indentação
-
Siga estes estilos de indentação para sintaxe JSX. eslint:
react/jsx-closing-bracket-location
// ruim <Componente primeiroParametro="bar" maisUmParametro="baz" /> // ideal <Componente primeiroParametro="bar" maisUmParametro="baz" /> // Se for apenas um parâmetro coloque na mesma linha. <Componente bar="bar" /> // children recebe indentação normal. <Componente primeiroParametro="bar" maisUmParametro="baz" > <ComponenteFilho /> </Componente>
Aspas
- Sempre usa aspas duplas (
"
) para atributos, mas aspas simples para todos os outros JS usados no componente. eslint:jsx-quotes
Sério? Atributos JSX can't contain escaped quotes, assim aspas fazem conjunções como
"Don't"
tornando-se mais fáceis de digitar. atributos regulares HTML também costumam usar aspas duplas em vez de únicas, de modo atributos JSX espelhão esta convenção.
```jsx
// ruim
<Componente bar='bar' />
// ideal
<Componente bar="bar" />
// ruim
<Componente style={{ left: "20px" }} />
// ideal
<Componente style={{ left: '20px' }} />
```
Espaçamento
-
Sempre inclua um único espaço no fechamento de suas tags que não recebem
childrens
.// ruim <Foo/> // tá de sacanagem néh? <Foo /> // ruim <Foo /> // ideal <Foo />
-
Não precisa usar espaço dentro nas chaves de parâmetros de um componente. eslint:
react/jsx-curly-spacing
// ruim <Foo bar={ baz } /> // ideal <Foo bar={baz} />
Props
-
Sempre use
camelCase
para prop names.// ruim <Componente UserName="hello" phone_number={12345678} /> // ideal <Componente userName="hello" phoneNumber={12345678} />
-
Quando o valor Booleano for
true
pode ser omitido. eslint:react/jsx-boolean-value
// ruim <Component hidden={true} /> // ideal <Component hidden />
-
Sempre inclua o parâmetro
alt
em suas<img>
tags. Ealt
pode ser uma string vazia em<img>
. eslint:jsx-a11y/img-has-alt
// ruim <img src="hello.jpg" /> // ideal <img src="hello.jpg" alt="Me waving hello" /> // ideal <img src="hello.jpg" alt="" />
-
Não use palavras como "image", "photo", ou "picture" no
alt
de sua<img>
. eslint:jsx-a11y/img-redundant-alt
Sério? Screenreaders já interpretam
img
como um elemento de imagem, por isso não há necessidade de incluir esta informação no texto do alt.
```jsx
// ruim
<img src="hello.jpg" alt="Picture of me waving hello" />
// ideal
<img src="hello.jpg" alt="Me waving hello" />
```
-
Use apenas válido, não- abstrato ARIA roles. eslint:
jsx-a11y/aria-role
// ruim - não é uma ARIA role <div role="datepicker" /> // ruim - abstrata ARIA role <div role="range" /> // ideal <div role="button" />
-
Não use
accessKey
em seus elementos. eslint:jsx-a11y/no-access-key
Sério? Inconsistências entre os atalhos de teclado e comandos de teclado usados por pessoas que usam leitores de tela e teclados podem complicar a acessibilidade.
// ruim
<div accessKey="h" />
// ideal
<div />
- Evite usar
index
comokey
de props, opte por um ID. (Sério?)
// ruim
{todos.map((todo, index) =>
<Todo
{...todo}
key={index}
/>
)}
// ideal
{todos.map(todo => (
<Todo
{...todo}
key={todo.id}
/>
))}
Refs
-
Sempre use
ref callbacks
. eslint:react/no-string-refs
// ruim <Foo ref="myRef" /> // ideal <Foo ref={(ref) => this.myRef = ref} />
Parenteses
-
Coloque Tags JSX entre parênteses quando eles abrangem mais de uma linha. eslint:
react/wrap-multilines
// ruim render() { return <Componente className="long body" foo="bar"> <ComponenteFilho /> </Componente>; } // ideal render() { return ( <Componente className="long body" foo="bar"> <ComponenteFilho /> </Componente> ); } // ideal, para uma linha. render() { const body = <div>hello</div>; return <Componente>{body}</Componente>; }
Tags
-
Sempre que a Tag não possuir
children
use self-close ( ). eslint:react/self-closing-comp
// ruim <Foo className="stuff"></Foo> // ideal <Foo className="stuff" />
-
Se o seu componente tiver mais de uma linha de propriedades(props), feche a Tag em uma nova linha. eslint:
react/jsx-closing-bracket-location
// ruim <Foo bar="bar" baz="baz" /> // ideal <Foo bar="bar" baz="baz" />
Métodos (Methods)
-
Use arrow functions para variáveis locais.
function ItemList(props) { return ( <ul> {props.items.map((item, index) => ( <Item key={item.key} onClick={() => fazerAlgoCom(item.name, index)} /> ))} </ul> ); }
-
Manipuladores de evento do método render dentro do
constructor()
eslint:react/jsx-no-bind
// ruim class extends React.Component { onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv.bind(this)} /> } } // ideal class extends React.Component { constructor(props) { super(props); this.onClickDiv = this.onClickDiv.bind(this); } onClickDiv() { // do stuff } render() { return <div onClick={this.onClickDiv} /> } }
-
Não use underscore prefix para métodos internos de um componente React.
// ruim React.createClass({ _onClickSubmit() { // do stuff }, // other stuff }); // ideal class extends React.Component { onClickSubmit() { // do stuff } // other stuff }
-
Certifique-se de retornar um valor em seu método
render
. eslint:require-render-return
// ruim render() { (<div />); } // ideal render() { return (<div />); }
Prioridades
- Prioridades para
class extends React.Component
:
- opcional
static
constructor
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers ou eventHandlers tipo
onClickSubmit()
ouonChangeDescription()
- getter methods para o
render
tipogetSelectReason()
ougetFooterContent()
- Métodos opcionais de render tipo
renderNavigation()
ourenderProfilePicture()
render
-
Como definir
propTypes
,defaultProps
,contextTypes
, etc...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;
-
Prioridades para
React.createClass
: eslint:react/sort-comp
displayName
propTypes
contextTypes
childContextTypes
mixins
statics
defaultProps
getDefaultProps
getInitialState
getChildContext
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
- clickHandlers ou eventHandlers tipo
onClickSubmit()
ouonChangeDescription()
- getter methods for
render
tipogetSelectReason()
ougetFooterContent()
- Optional render methods tipo
renderNavigation()
ourenderProfilePicture()
render
isMounted
- Não use
isMounted
. eslint:react/no-is-mounted
Sério?
isMounted
é um anti-pattern, não estára mais disponível nas classes ES6 (ECMA2015), e está a caminho de ser oficialmentedeprecated
(descontinuado).
Translation
This JSX/React style guide is also available in other languages:
- Chinese (Simplified): JasonBoy/javascript
- Polish: pietraszekl/javascript
- Korean: apple77y/javascript
- Brazilian: ronal2do/javascript