Zup ESlint config for React and Javascript
Os padrões que iremos adotar para serem utilizados em nossos projetos.
Este guia foi criado para mantermos o estilo de código React que adotamos aqui na Zup, e algumas práticas que nós consideramos ser adequadas. Nosso estilo é baseado no Airbnb com algumas modificações.
Qual o propósito de utilizarmos um Style Guide?
O principal objectivo é mantermos uma única forma de escrita, porém também ganhamos:
- Melhor Legibilidade de código
- Melhor manutenção do código
- Ganho de tempo em code reviews
- Padrão de desenvolvimento
- Boas práticas de programação
- Clean Code
- Entre outros grandes benefícios
``shell`
yarn add --dev eslint@4.19.1 eslint-config-zup-react
Crie um arquivo .eslintrc.js na pasta raiz do seu projeto com o seguinte conteúdo:
`json`
module.exports = {
"extends": "zup-react"
}
`
Button/
├── index.jsx
`
$3
- Quando necessário criar um componente que terá estilos, sempre opte por styled-components e com a seguinte estrutura:`
Button/
├── index.jsx
└── styled.js
`$3
- Sempre que for extender uma classe com Component ou PureComponent faça a destruturação na importação.
`Javascript
// Bad
import React from 'react'
class Classe extends React.Component// Good
import React, { Component } from 'react'
class Classe extends Component
`$3
`Javascript
// Very Bad
import React from 'react'
const Classe = React.createClass({
render() {
....
}
})// Bad
import React from 'react'
class Classe extends React.Component {
render() {
....
}
}
// Good
import React, { Component } from 'react'
class Classe extends Component {
render() {
....
}
}
`$3
- Prefira utilizar a sintaxe funcional para componentes sem estado e em dumb components.
`Javascript
const Title = (props) => (
{props.title}
)
`$3
- Prefira utilizar a sintaxe de classes para componentes que possuem conhecimento do estado, em container e componentes que utilizem lifecycles.
`Javascript
class Title extends Component {
render () {
return (
....
)
}
}
`$3
- Caso seja necessário criar um estado local na sua classe utilize a seguinte abordagem:
`Javascript
// Bad
class Example extends Component {
componentWillMount() {
this.state = {
loading: true
}
}
}// God
class Example extends Component {
constructor() {
super()
this.state = {
loading: true
}
}
}
// Best
class Example extends Component {
state = {
loading: true
}
}
`$3
- Na utilização de objetos, sempre adicione vírgula no último element, isso irá auxiliar na visualização do git diff, caso haja adição de um novo elemento na última posição.
`Javascript
// Bad
export {
Provider,
Consumer
}// Good
export {
Provider,
Consumer,
}
`$3
- Sempre prefira escrever funções com arrow functions, principalmente se o retorno couber apenas em uma linha, e quando houver callbacks com funções anônimas.
`Javascript
// Very Bad
function double(array) {
return array.map(function(item) {
return item * 2
})
}// Good
function double(array) {
return array.map(item => item * 2)
}
// Best
const double = array => array.map(item => item * 2)
`$3
- Sempre que possível, utilize const na inicialização de qualquer variável.
`Javascript
// Bad
var a = 1// Good
const a = 1
`$3
- Dê preferência ao uso de template strings na concatenação de strings.
`Javascript
// Bad
const person = {
name: 'Isac'
}
const myName = "My name is "+ person.name+"."// God
const person = {
name: 'Isac'
}
const myName =
My name is ${person.name}.
`$3
`Javascript
// Bad
import React from 'react';// Good
import React from 'react'
`$3
- Nunca deixe console.log() em seu código
`Javascript
// Bad
const sum = (a, b) => {
const result = a + b
console.log(result)
}
`$3
- Nunca deixa comentários em seu código
`Javascript
// Bad
// Função que soma dois elementos
const sum = (a, b) => a + b// Good
const sum = (a, b) => a + b
`$3
- Sempre que possível, omita o return
`Javascript
// Bad
const Bonus = () => {
return (
Zup Style Guide
)
}// Good
const Bonus = () => (
Zup Style Guide
)
`$3
- Sempre que possível, utilize destruturação de objetos
`Javascript
// Bad
const Title = (props) => (
{props.title}
)// Good
const Title = ({ title }) => (
{title}
)
`$3
- Caso o seu arquivo contenha somente um elemento a ser exportado, utilize export default
`Javascript
class ClasseNameA extends Component {
render() {
....
}
}export default ClasseNameA
`$3
- Sempre que retornar um elemento JSX, envolva em um elemento pai. Caso esteja utilizando versão superior a React 16.2, prefira Fragment, ou sintaxe curta de Fragment.
`Javascript
// Bad
import React from 'react'const NameA = () => (
....
)// Good
import React, { Fragment } from 'react'
const NameA = () => (
....
)
// Best
import React, { Fragment } from 'react'
const NameA = () => (
<>
....
>
)
`$3
- Caso haja a necessidade de repassar props para outros componentes, defina-as e utilize nomes semânticos, ao invés de utilizar spread. Isso irá facilitar o entendimento do fluxo, e quais props estão sendo utilizadas. Evitando a passagem desnecessárias de outras.
`Javascript
// Bad
const Button = props => (
{props.children}
)// Good
const Button = ({ primary, children }) => (
{children}
)
`$3
- Caso esteja sendo necessário criar bind para o contexto this, prefira utilizar métodos com arrow function.
`Javascript
// Bad
class MyComponent extends Component {
constructor() {
super()
this.methodA = this.methodA.bind(this)
} methodA() { ... }
}
// Good
class MyComponent extends Component {
methodA = () => { ... }
}
`$3
- React > 16.3: Não utilize componentWillMount para iniciar o seu state
`Javascript
// Bad
class MyComponent extends Component {
componentWillMount() {
this.setState({
currentColor: this.props.defaultColor,
palette: 'rgb'
})
}
}// Good
class MyComponent extends Component {
state = {
currentColor: this.props.defaultColor,
palette: 'rgb'
}
}
`$3
- React > 16.3: Sempre prefira o uso do componetDidMount ao invez do componentWillMount, o mesmo será descontinuado na versão 17.
`Javascript
// Bad
class MyComponent extends Component {
componentWillMount() {
...
}
}
// Good
class MyComponent extends Component {
componentDidMount() {
...
}
}
`$3
- React > 16.3: Este é um exemplo de verificação de props para atualização do estado. Sempre que se deparar com tal situação, utilize getDerivedStateFromProps para realizar tal operação. ComponentWillReceiveProps será descontinuado na versão 17.
`Javascript
// Bad
class ExampleComponent extends Component {
state = {
isScrollingDown: false
}; componentWillReceiveProps(nextProps) {
if (this.props.currentRow !== nextProps.currentRow) {
this.setState({
isScrollingDown:
nextProps.currentRow > this.props.currentRow
})
}
}
}
// Good
class ExampleComponent extends Component {
state = {
isScrollingDown: false,
lastRow: null
}
getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.currentRow !== prevState.lastRow) {
return {
isScrollingDown:
nextProps.currentRow > prevState.lastRow,
lastRow: nextProps.currentRow
}
}
return null
}
}
`$3
- React > 16.3: Caso queira executar alguma ação após o componente receber alguma chamada externa, prefira o uso de componentDidUpdate, pois componentWillUpdate será descontinuado na versão 17.
`Javascript
// Bad
class ExampleComponent extends Component {
componentWillUpdate(nextProps, nextState) {
if (this.state.someStatefulValue !== nextState.someStatefulValue) {
nextProps.onChange(nextState.someStatefulValue);
}
}
}// Good
class ExampleComponent extends Component {
componentDidUpdate(prevProps, prevState) {
if (this.state.someStatefulValue !== prevState.someStatefulValue) {
this.props.onChange(this.state.someStatefulValue)
}
}
}
`$3
- PureComponent é similar ao Component. A diferença está no shouldComponentUpdate(). Em PureComponent isto é feito de forma superficial no estado e props. Utilize PureComponent somente em casos em que você saiba exatamente a estrutura das propriedades que irão ser recebidas pelo component. Em alguns casos, onde o seu componente sempre irá renderizar uma mesma estrutura, você pode utilizar para ganhar performance.
Mais informações você vai encontrar na documentação do React.$3
- Sempre que possível, crie valores padrões nos parâmetros da sua função`Javascript
// Bad
const getPrice = (amount, scale, currency) => {
return priceNormalize(parseFloat(inScale(amount, scale), 10), currency)
}// Good
const getPrice = (amount = 0, scale = 2, currency = 'BRL') => {
return priceNormalize(parseFloat(inScale(amount, scale), 10), currency)
}
`$3
- When creating classes use blank line after
`Javascript
// Bad
class MyComponent extends Component {
componentDidMount() {
...
}
}// Good
class MyComponent extends Component {
componentDidMount() {
...
}
}
`$3
- When return used requires a blank line between a variable declaration and a return statement
`Javascript
// Bad
render () {
const { name } = this.props
return (
{name}
)
}// Good
render () {
const { name } = this.props
return (
{name}
)
}
``