React - Como iniciar um projeto?
Tags: javascript, react, beginners
Published: 2021-02-08 01:15:35

##:beginner: Introdução

Nesse post vamos criar nossa primeira aplicação React utilizando o template [Create-React-App](https://github.com/facebook/create-react-app) e [Typescript](https://www.typescriptlang.org/), um superset de Javascript que adiciona tipagem e várias outra funcionalidades mais atuais da linguagem.

##:memo: Pré-requisitos

* [Node.js](https://nodejs.org/pt-br/download/package-manager/) instalado na sua versão LTS.
* [VSCode](https://code.visualstudio.com/download) ou qualquer outro editor de código da sua preferencia.
* Um browser qualquer.

:warning: Esse tutorial foi desenvolvido utilizando o Linux, e é possível que algum comando talvez não funcione exatamente no Windows ou Mac. Nesses casos, Google é seu melhor amigo.

##:telescope: Conhecendo o projeto

![Page](https://dev-to-uploads.s3.amazonaws.com/i/1t9wat99faudrackh2h1.png)
 

Nós vamos criar um projeto chamado de GoFinances, um gerenciador de gastos. Nele vamos poder cadastrar saídas e entradas de dinheiro, além de informar a categoria desse valor.

Algo básico, mas um bom projeto para começar.

##:computer: Criando projeto com CRA

Primeiramente escolha a pasta onde você vai trabalhar no seu novo projeto e acesse ele pelo terminal. Se tiver instalado corretamente o Node, você terá acesso a um comando chamado `npx`. Com ele é possível executar códigos externos sem a necessidade de baixá-los e instalá-los em nossa máquina. 

O comando completo é:

```bash
npx create-react-app go-finances --template=typescript
```

O que significa cada parte desse comando:

* `npx` executa o comando.
* `create-react-app` é pacote que será usado para criar o template da nossa aplicação.
* `go-finances` é o nome do projeto.
* `--template=typescript` é para sobrescrever o template padrão para o que utiliza o typescript.

Após rodar esse comando, o projeto e todas suas dependências começaram a serem baixadas, e assim que terminar, bastar rodar...
```bash
cd go-finances
```
... para entrar na pasta do projeto, e...
```bash
npm start
```
... para abrir no seu browser padrão.

Você deve ver uma tela como essa: 
![Print #1](https://dev-to-uploads.s3.amazonaws.com/i/qmseja9qxb4tgcg2tgre.png)

Abrindo o projeto no VSCode vamos encontrar uma estrutura como essa:
```bash
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── README.md
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
├── tsconfig.json
└── yarn.lock
```
Vamos começar a limpar essa estrutura. Na pasta `public` vamos deixar apenas o `index.html` e `favicon.ico`. Dentro do `index.html` vamos apagar tudo que não é necessário por agora deixando apenas:

```html
<!DOCTYPE html>
<html lang="pt_BR">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Go Finances"
    />
    <title>Go Finances</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```
Tá vendo essa `<div id="root"></div>`? É dentro dela que toda nossa aplicação vai ser renderizada pelo React. Então ela é bem importante. Não apaguem ela!  

Na pasta `src`, vamos deixar `App.tsx`, `index.tsx` e `react-app-env.d.ts` por enquanto e mudando o conteúdo do `index.tsx` para:

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
```

Esse arquivo é a entrada da nossa aplicação. No fim do arquivo dá pra ver que a lib `react-dom` renderiza o conteúdo do primeiro parâmetro na `<div id="root"></div>`.

Agora o `App.tsx`:

```react
function App() {
  return (
    <div>
      <header>
        <p>
          Edite <code>src/App.tsx</code> e salve para recarregar.
        </p>
        <a
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Aprenda React
        </a>
      </header>
    </div>
  );
}

export default App;
```

Se você não cancelou o `npm start`, basta acessar no seu browser *http://localhost:3000* e verá algo como isso:

![Print #2](https://dev-to-uploads.s3.amazonaws.com/i/nk0hc4mv8xoivqzboh1b.png) 

:warning: Vale ressaltar de que desde a versão 17 do React não é mais necessário importar o React em cada arquivo. Se você tiver trabalhando em um projeto em uma versão anterior, é necessário adicionar `import React from 'react'` na primeira linha do `App.tsx`. E não se esqueça do `export default nome-do-componente`, sem ele o componente não poderá ser importado em outro arquivo.

##:package: Componentização

Esse é o um dos mais importantes conceitos do React e você já está utilizando. Tudo na nossa aplicação é um componente. O arquivo `App.tsx` é o componente principal dessa aplicação. O que define um componente para mim é: "Uma função que recebe parâmetros e retorna um conteúdo JSX".

Os parâmetros ficam para o próximo tópico, mas o que é JSX?

JSX é o HTML dentro do Javascript. No nosso caso usando Typescript os aquivos que são componentes tem terminação `*.tsx`. Lembrando que todos componentes devem iniciar com letra maiúscula.

Todo componente pode ser importado e utilizado dentro de outro componente, ou até mesmo dentro um arquivo normal TS (ou JS).

Vamos criar o primeiro componente que será o header (cabeçalho). Primeiro, dentro da pasta `src`, vamos criar uma pasta `components` onde ficaram guardados todos nossos componentes. Criaremos um arquivo assim:
```react
// components/Header.tsx

function Header() {
  return (
    <div>
      <header>
        <span>Go Finance</span>
        <nav>
          <a href="#">Listagem</a>
          <a href="#">Cadastro</a>
        </nav>
      </header>
    </div>
  )
}

export default Header
```
E importaremos no `App.tsx`: 

```react
import Header from "./components/Header";

function App() {
  return (
    <div>
      <Header />
    </div>
  );
}

export default App;

```

Agora com esse componente de Header podemos reutilizá-lo em todas as telas, e se qualquer mudança for necessária basta alterar o componente e a mudança será refletida em todas as telas.

##:wrench: Propriedade

Como fazemos para alterar um componente sem ter que mudar o código? E se em cada tela diferente quiséssemos que o texto dentro do Header fosse diferente? É aí que entra as propriedades.
```react
// components/Header.tsx

type HeaderProps = {
  title?: string
}

function Header(props: HeaderProps) {
  return (
    <div>
      <header>
        <span>{props.title ?? 'Go Finances'}</span>
        <nav>
          <a href="#">Listagem</a>
          <a href="#">Cadastro</a>
        </nav>
      </header>
    </div>
  )
}

export default Header
```
Todas as propriedades de um componente vem dentro do argumento `props`. Já que estamos utilizando Typescript vamos *tipar* as propriedades com o tipo `HeaderProps` indicando que o objeto `props` tem um valor opcional `title` que deve ser uma `string`. Para adicionar o valor no JSX basta colocar a variável `props.title` entre *{}*. Caso nada seja passado para essa propriedade o valor padrão é *Go Finances*.

Podemos melhorar esse código utilizando de [desestruturação](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Operators/Atribuicao_via_desestruturacao#desestrutura%C3%A7%C3%A3o_de_objeto):
```react
// components/Header.tsx

type HeaderProps = {
  title?: string
}

function Header({ title = 'Go Finances' }: HeaderProps) {
  return (
    <div>
      <header>
        <span>{title}</span>
        <nav>
          <a href="#">Listagem</a>
          <a href="#">Cadastro</a>
        </nav>
      </header>
    </div>
  )
}

export default Header
```
E no `App.tsx`:

```react 
import Header from "./components/Header";

function App() {
  return (
    <div>
      <Header />
      <Header title="Titulo Novo" />
    </div>
  );
}

export default App;
```

Para passar um valor que não seja string utilizamos *{}*: 
```react
// number
<Component prop={1} />

// array
<Component prop={[1, 2, 3]} />

//object
<Component prop={{ a: 1, b: 2, c: 3 }} />

// true
<Component prop={true} />
      or
<Component prop />

//false
<Component prop={false} />
```
Uma propriedade especial que o próprio React adiciona é o `children` que nada mais é que o conteúdo de um componente.
Imagine que dentro do Header queremos passar também os links, como podemos fazer isso?

```react
function App() {
  return (
    <div>
      <Header>
        <a href="/">Home</a>
        <a href="/sobre">Sobre</a>
        <a href="/login">Login</a>
      </Header>
    </div>
  );
}
```

```react
// components/Header.tsx

import { ReactNode } from "react"

type HeaderProps = {
  children?: ReactNode
}

function Header({ children } : HeaderProps) {
  return (
    <div>
      <header>
        <span>Go Finances</span>
        <nav>
          {children}
        </nav>
      </header>
    </div>
  )
}
```


Vamos voltar o código para como estava no fim no tópico de Componentização.

##:bulb: Estado e Imutabilidade

Vamos criar um novo componente para essa explicação e importar no `App.tsx` para ver na tela:

```react
// components/TransactionList.tsx

function TransactionList() {
  return (
    <div />
  )
}

export default TransactionList
```

```react 
import Header from "./components/Header";
import TransactionList from "./components/TransactionList";

function App() {
  return (
    <>
      <Header />
      <TransactionList />
    </>
  );
}

export default App;
```
:pushpin: O React não aceita que o `return` tenha mais de um componente diretamente um abaixo do outro, por isso estamos utilizando o `<></>` por volta dos dois. 
Eles servem para agrupar os componentes sem ter que renderizar uma `<div>` em volta por exemplo.

No componente `TransactionList.tsx` vamos salvar uma lista fictícia de transações e tentar renderiza-las em uma `<ul>`:

```react
// components/TransactionList.tsx

function TransactionList() {
  const transactions = [
    '-R$ 100,00 - Compra de Alimentos - 22/11/2020', 
    '-R$50,00 - Gasolina - 20/12/2020', 
    'R$32,00 - Investimento - 22/12/2020'
  ];

  return (
    <ul>
      {transactions.map((transaction, i) => (
        <li key={i}>{transaction}</li>
      ))}
    </ul>
  )
}

export default TransactionList
```

Criamos inicialmente uma lista de strings que contém nossas transações. Depois retornamos no componente uma lista (`<ul>`) que renderiza todos as `transactions` através de um `map` que retorna uma `<li>` que tem como conteúdo cada item da nossa lista.

Há também a propriedade `key` que recebe um valor único entre os elementos da lista. Como não temos essa valor ainda, vamos colocar o index de cada transação.

A [documentação](https://pt-br.reactjs.org/docs/lists-and-keys.html) diz:
 > As chaves ajudam o React a identificar quais itens sofreram alterações, foram adicionados ou removidos.

A chave deve ser colocada no elemento mais "externo" do retorno do `map`. Caso você não coloque aparecerá um erro como esse: 

![Print #3](https://dev-to-uploads.s3.amazonaws.com/i/6e8828bk90aorg2uomx3.png)
  
Vamos agora criar um botão para adicionar uma nova transação na lista.

```react 
// components/TransactionList.tsx

function TransactionList() {
  const transactions = [
    '-R$ 100,00 - Compra de Alimentos - 22/11/2020', 
    '-R$50,00 - Gasolina - 20/12/2020', 
    'R$32,00 - Investimento - 22/12/2020'
  ];

  function handleAddTransaction() {
    console.log('clicado')
  }

  return (
    <>
      <ul>
        {transactions.map((transaction, i) => (
          <li key={i}>{transaction}</li>
        ))}
      </ul>
      <button onClick={handleAddTransaction}>
        Adicionar Transação
      </button>
    </>
  )
}

export default TransactionList
```

Para adicionar uma função que é disparada ao clicar no botão, basta criar a função e adiciona-lá a propriedade `onClick`. Teste no seu projeto e veja no console (`ctrl + shift + i`) do browser se está funcionando.

Se mudarmos o código da função para adicionar uma nova transação na lista ficaria assim:
```javascript
function handleAddTransaction() {
   transactions.push('Nova transação')

   console.log(transactions)
 }
```
Porém se abrirmos nossa aplicação e clicarmos no botão veremos que a tela não é atualizada, mas no console aparece que a lista está recebendo novos items.

![Print #4](https://dev-to-uploads.s3.amazonaws.com/i/goigiezmlutw24nf7lm9.png)
 
Isso acontece porque o React não sabe que deve atualizar a tela apenas de mudarmos o valor da variável `transactions`. Temos que criar um estado que guardará a lista de transações. Para isso utilizaremos o hook [useState](https://pt-br.reactjs.org/docs/hooks-state.html).

```react
// components/TransactionList.tsx

import { useState } from "react";

function TransactionList() {
  const [transactions, setTransactions] = useState([
    '-R$ 100,00 - Compra de Alimentos - 22/11/2020', 
    '-R$50,00 - Gasolina - 20/12/2020', 
    'R$32,00 - Investimento - 22/12/2020'
  ])

  function handleAddTransaction() {
    console.log(transactions)
  }

  return (
    <>
      <ul>
        {transactions.map((transaction, i) => (
          <li key={i}>{transaction}</li>
        ))}
      </ul>
      <button onClick={handleAddTransaction}>
        Adicionar Transação
      </button>
    </>
  )
}

export default TransactionList
```
O `useState` retorna um array, sendo a primeira posição a valor real do estado e como segunda posição uma função utilizada para alterar esse estado.

Como parâmetro ele recebe o valor inicial do estado. No nosso caso são os valores das primeiras transações de teste.

Para alteramos o valor de `transactions` passamos o novo valor para a função `setTransactions`. Ai entra a imutabilidade. Não devemos alterar o valor do estado diretamente como fizemos anteriormente usando `transactions.push('Nova transação')`. Devemos criar uma nova lista de transações que contenha os valores anterior da lista e adicionando o novo valor:

```javascript
function handleAddTransaction() {
    setTransactions([...transactions, 'Nova Transação'])
}
```

Assim deixamos a cargo do React alterar o estado, e consequentemente alterar a tela.

![Print #5](https://dev-to-uploads.s3.amazonaws.com/i/sq8843zu6uacubridgp6.png)
 
Utilizamos o `useState` quando precisamos salvar um valor que será utilizado para alterar a tela ou algum componente. Poderia ser por exemplo o número de notificações não lidas pelo usuário, ou o número de likes em foto ou até a lista de comentários de uma postagem. Todos são valores que, se alterados, devem alterar o que o usuário vê.

##:sweat_smile: Só isso tudo?

É bastante coisa para aprender de uma vez. O que eu aconselho é entre esse e o próximo tutorial você teste algumas das suas ideias utilizando *Componentização*, *Propriedade* e *Estado*. Talvez criar um pequeno contador que diminui e aumente o valor recebido por propriedade... Bem são infinitas possibilidades.

Se for seguir meu conselho tente algo simples, nada de tentar começar com a próxima ideia revolucionaria de uma nova empresa do Elon Musk.

Bem... por enquanto, isso é tudo pessoal!

No próximo post vamos iniciar de verdade nosso projeto já estilizando a aplicação.

PS: Um agradecimento especial:purple_heart: ao pessoal da [Rocketseat](https://rocketseat.com.br/):rocket: pelo conteúdo de qualidade em React.