# DevHat JavaScript/React Style Guide() {

Reference Style Guide

- [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)
- [Airbnb](https://github.com/airbnb/javascript/tree/master)

## Sumário:

1.  [Regras básicas](#regras-basicas)
2.  [Estrutura de componentes](#estrutura-de-componentes)
3.  [Criando componentes](#criando-componentes)
4.  [Exportando arquivos](#exportando-arquivos)
5.  [Custom hooks](#custom-hooks)
6.  [Arquivos em PascalCase](#arquivos-em-pascalcase)
7.  [Nomeando coisas](#nomeando-coisas)
8.  [Class Component](#class-component)
9.  [Estilizando componentes](#estilizando-componentes)
10. [Tipando componentes](#tipando-componentes)
11. [Testes unitários](#testes-unitários)
12. [Alt em imagens](#alt-em-imagens)
13. [Estruturas de pastas](#estrutura-de-pastas)

<a name="regras-basicas"></a>
<a name="estrutura-de-componentes"></a>
<a name="criando-componentes"></a>
<a name="exportando-arquivos"></a>
<a name="custom-hooks"></a>
<a name="arquivos-em-pascalcase"></a>
<a name="nomeando-coisa"></a>
<a name="class-component"></a>
<a name="estilizando-componentes"></a>
<a name="tipando-componentes"></a>
<a name="testes-unitários"></a>
<a name="alt-em-images"></a>
<a name="estrutura-de-pastas"></a>

## Regras básicas

- Um componente por arquivo
- Evite ao máximo o uso de `any` nas tipagens
- Componentes unicamente em TSX
- Código apenas em inglês
  > `Por que? Por mais que todos os contribuídores sejam brasileiros é importante padronizarmos todo o código em inglês para evitar uma mistura de inglês e português, algo do tipo "setNome()", um dos principais motivos também é a acessibilidade, muitas ferramentas de tradução automática e leitores de tela são mais eficazes quando lidam com texto em inglês.`

## Estrutura de componentes

- Separe a pasta do seu componente em 4 arquivos
  - Componente.tsx (seu componente em si)
  - Componente.spec.tsx (testes do componente)
  - Componente.module.scss (seus estilos)
  - Componente.types.ts (interfaces e types do componente)

```
├─ components
│  ├─ MyComponent.module.scss
│  └─ MyComponent.spec.tsx
│  └─ MyComponent.tsx
|  └─ MyComponent.types.ts
```

## Criando componentes

Todos os componentes serão criados em **`funções normais`**, `arrow functions` **apenas** dentro dos componentes

```ts
// Bom
function Component(props: IProps) {
	const handleSomething = () => { /* ... */ }
	return ( /* ... */ )
}

// Ruim
const Component = (props: IProps) => {
	const handleSomething = () => { /* ... */ }
	return ( /* ... */ )
}

// Ruim
const Component = (props: IProps) => {
	function handleSomething() { /* ... */ }
	return ( /* ... */ )
}
```

## Exportando arquivos

Iremos usar **SEMPRE** `export default` nos componentes

```ts
// Bom
function Component(props: IProps) {
	return ( /* ... */ )
}

export default Component

// Ruim
export function Component(props: IProps) {
	return ( /* ... */ )
}

// Ruim
function Component(props: IProps) {
	const handleSomething = () => { /* ... */ }
	return ( /* ... */ )
}
```

Com excessão dos componentes, não iremos usar export default

```ts
// Bom
export interface IProps {
  /* ... */
}

// Ruim
interface IProps {
  /* ... */
}
export default IProps;
```

Isso também vale para `custom hooks`

```ts
// Bom
export const useHook = () => {
  /* ... */
};

// Ruim
const useHook = () => {
  /* ... */
};
export default useHook;
```

## Custom hooks

Se precisar criar um custom hook, use `arrow functions`

```ts
// Bom
export const useHook = () => {
  /* ... */
};

// Ruim
export function useHook() {
  /* ... */
}
```

## Componentes em PascalCase

Iremos seguir o padrão PascalCase que consiste em nomear todas as palavras com a primeira letra maiúscula.

```
├─ components
│  ├─ MyComponentHere.tsx
```

## Nomeando coisas

Tirando componentes e interfaces, iremos utilizar `camelCase` para nomear tudo.

```ts
// Bom
const handleSomething = () => {
  /* ... */
};

// Ruim
const HandleSomething = () => {
  /* ... */
};

// Ruim
const handle_something = () => {
  /* ... */
};
```

Isso Inclue props de componentes

```ts
<MyComponent
	isHandsome
	name="hxsggsz"
/>
```

Se a prop é uma string sempre passe entre aspas, única excessão é se você for usar `template string`

```ts
// Bom
<MyComponent
	isHandsome
	name="hxsggsz"
/>

// Ruim
<MyComponent
	isHandsome
	name={"hxsggsz"}
/>
```

Oculte parâmetros que sempre serão `true`

```ts
// Bom
<button isLoading>teste<button>

// Ruim
<button isLoading={true}>teste<button>
```

## Class component

Nosso projeto está sendo feito inteiramente com `programação funcional`, então apenas use `functional components` _(salvo excessões bem excessíveis)_:

```ts
// Bom
function Component(props: IProps) { /* ... */ }

export default Component

// Ruim
class Component extends React.Component {
  // ...
  render() {
    return ( /* ... */ )
  }
}
```

## Estilizando componentes

Estamos utilizando `scss modules` para estilização, ele tem umas diferenças do css normal

```scss
// Bom
.button {
  /* seu css aqui */
  &:hover {
    /* seu css de hover aqui*/
  }
}

// Ruim
.button {
  /* seu css aqui */
}
.button:hover {
  /* seu css de hover aqui*/
}
```

use `scss modules` sempre

```tsx
// Bom
import scss from './Component.module.scss';

function Component(props: IProps) {
  return <div className={scss.style} />;
}

// Ruim
import './Component.scss';

function Component(props: IProps) {
  return <div className="style" />;
}
```

Evite _inline-css_, sempre crie uma classe para estilizar.
_Existem excessões em que é precisa usar `inline styles`, mas são casos específicos e estarão atrelados a apenas uma propriedade_

```tsx
// Bom
import scss from './Component.module.scss';

function Component(props: IProps) {
  return <div className={scss.style} />;
}

// Ruim
function Component(props: IProps) {
  return <div style={{ color: '#fff' }} />;
}
```

## Tipando componentes

Priorize `Interfaces` no lugar de `Types` , ambos servem para fazer a mesma coisa, mas estamos seguindo o padrão de interfaces

```ts
// Bom
interface IProps {
  /* ... */
}

// Ruim
type IProps = {
  /* ... */
};
```

Use o Prefixo `I` na hora da criação de interfaces.

```ts
// Bom
interface IProps {
  /* ... */
}

// Ruim
interface PropTypes {
  /* ... */
}
```

Use o Prefixo `T` na hora da criação de tipos.

```ts
// Bom
type TProps = {
  /* ... */
};

// Ruim
type PropTypes = {
  /* ... */
};
```

Use o Prefixo `E` na hora da criação de enums.

```ts
// Bom
enum ECoisas = { /* ... */ }

// Ruim
type Coisas = { /* ... */ }
```

## Testes unitários

Tente ser o mais claro para descrever seus testes, descreva a ação que você vai fazer como `describe()` e use o `it()` para descrever a ação esperada do teste. Siga esse padrão:
_Evite a palavra "should" seguida do `it`, faça sua sentença ser hiperativa, como "it has", "it renders", "it fails" e etc. Isso serve pra evitar que toda descrição de um teste inicie por "should"._

```ts
describe('MyButtonComponent', () => {
  describe('when initialize', () => {
    it('shows the button on screen', () => {
      // ...
    });

    describe('when click', () => {
      it('calls the handleButton function ', () => {
        // ...
      });
    });
  });
});
```

## Alt em imagens

SEMPRE coloque o atributo `alt` quando for usar alguma imagem no projeto, é bom por causa do `SEO` (mesmo que esse projeto não seja web) e acessibilidade.

```tsx
// Bom
<img src={image} alt="me and my dog" />

// Ruim
<img src={image} />
```

Evite usar o prefixo `image` ou `picture` porque os leitores de tela ja adicionam esse prefixo na hora de ler o `alt` então ficaria duplicado

```tsx
// Ruim
<img src={image} alt="image about me and my dog" />
```

## Estrutura de pastas do projeto

```

├─ public
│  ├─ coisas de fato publicas como robots.txt, favicons, sitemap.xml e etc.
├─ src
│  ├─ App.tsx
|  |  ├─ Root provider
│  ├─ components
|  |  ├─ Componentes de alta usabilidade
│  ├─ hooks
|  |  ├─ Hooks customizados de alta reusabilidade
│  ├─ pages
|  |  ├─ Páginas da aplicação
│  ├─ store
|  |  ├─ Store geral da aplicação
│  ├─ styles
|  |  ├─ Estilos globais
│  ├─ utils
|  |  ├─ Funções/classes de alta reusabilidade
│  ├─ services
|  |  ├─ Serviços externos a aplicação
│  ├─ config
|  |  ├─ Configurações de módulos
│  ├─ snippets
|  |  ├─ Snippets usados na aplicação
│  ├─ interfaces
|  |  ├─ Interfaces que não são relativas a um módulo específico
│  ├─ constants
|  |  ├─ Constantes que não são relativas a um módulo específico
│  ├─ enums
|  |  ├─ Enums que não são relativos a um módulo específico
```