Iniciando o projeto Insta Doguinhos (em ReactJS)
Tags: react, javascript
Published: 2020-10-21 13:01:17


Esse é o segundo projeto em React que inicio, e estou seguindo passo a passo o curso completo de React da Origamid, onde venho estudando Javascript desde o ano passado.

O início do projeto aborda conceitos de diversas coisas novas para mim: componentes, get, post, fetch que eu já conhecia, useState() (que estou ainda com dificuldades de entender totalmente), dentre outras coisas. O intuito desse post é compartilhar com vocês os avanços de meus estudos em programação. Pode ser que eu tenha noções que não estejam muito claras ainda e ficarei feliz com os comentários de vocês. 🙂

Vamos dar início ao projeto.

# Configuração e teste da API Dogs

A primeira coisa que fizemos foi testar a **API dogs**, então criamos uma pasta "api" e dentro delas criamos o componente **Api.js**, onde vamos colocar os outros componentes para poder postar as fotos do aplicativo e também recuperá-las na sequência.

Apenas um parênteses antes de continuar:

Estudando em outros tutoriais na internet, percebi uma diferença entre ese tutorial da Origamid com outros tutoriais de react, e os componentes eram escritos de maneiras diferentes. E nessas pesquisas, descobri que existem dois tipos de componentes em React: os componentes de classe e os componentes funcionais sem estado. Aquiv ai uma breve definição, que encontrei [nesse link](https://blog.geekhunter.com.br/criando-componentes-react-componentes-de-classe-e-funcional-sem-estado/#:~:text=Componentes%20de%20classe%20s%C3%A3o%20componentes,em%20qualquer%20lugar%20do%20componente).

**Componentes de classe**
Componentes de classe são componentes que possuem um alto nível de poder dentro da aplicação, pois além gerenciar o próprio estado, herdam os chamados métodos de ciclo de vida do React, lidam com partes lógicas da aplicação e manipulam eventos através de métodos que podem ser invocados em qualquer lugar do componente ou em seus filhos.

**Componentes funcionais sem estado**
Os componentes funcionais sem estado, são representados por funções *JavaScript* e como o nome sugere, não se preocupam (e nem devem se preocupar) com o gerenciamento de estado do componente, mas apenas com a apresentação dos dados na aplicação.

Portanto, percebi que nesse tutorial usaremos então os componentes funcionais sem estado. (assim que souber explicar melhor o porquê, venho aqui editar esse post :) )

O código **Api.js** ficou da seguinte forma:

```jsx
import React from 'react'
import PhotoGet from './endpoints/PhotoGet'
import PhotoPost from './endpoints/PhotoPost'
import TokenPost from './endpoints/TokenPost'
import UserPost from './endpoints/UserPost'

const Api = () => {
    return (
        <div>
            Minha Api
            <h2>USER POST</h2>
            <UserPost />

            <h2>TOKEN POST</h2>
            <TokenPost />

            <h2>PHOTO POST</h2>
            <PhotoPost />

            <h2>PHOTO GET</h2>
            <PhotoGet />
        </div>
    )
}

export default Api
```

Então aos pouquinhos estou entendendo o conceito de componentes dentro do React, e como fazemos para importar cada um deles em nosso aplicativo. Entendi que dessa forma fica muito mais organizado e fácil de modificar partes menores do aplicativo.

---

Agora vou falar sobre cada um desses componentes e explicar o que é feito dentro de cada um deles.

## USERPOST

O componente USERPOST servirá para criar um novo usuário na base de dados, e vai ter como elementos os seguintes itens:

- username
- email
- password

Por isso, logo dentro de nossa constante UserPost(), começamos declarando as constantes dos elementos reativos dessa componente:

```jsx
const [username, setUsername] = React.useState('')
const [email, setEmail] = React.useState('')
const [password, setPassword] = React.useState('')
```

Dessa forma, quando puxarmos essas constantes dentro do input, mais abaixo, elas são reativas. Na parte return deste componente, temos o seguinte código:

```jsx
<form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="username"
                value={username}
                onChange={({ target }) => setUsername(target.value)}
            />
            <input
                type="email"
                placeholder="email"
                value={email}
                onChange={({ target }) => setEmail(target.value)}
            />
            <input
                type="password"
                placeholder="password"
                value={password}
                onChange={({ target }) => setPassword(target.value)}
            />

            <button>Enviar</button>
        </form>
```

Cada input vai possuir um *type*, *placeholder*, *value* (com valor reativo dentro dele), e o método *onChange*, que chamará uma função de callback, puxando e atualizando o elemento target e o valor dele. Entendi que esse método onChange é algo que sempre vai puxar essa função de callback.

Quando enviarmos o formulário aprós o preenchimento, usaremos o método **onSubmit** e chamaremos a função handleSubmit, que será descrita logo abaixo:

```jsx
function handleSubmit(event) {
        event.preventDefault();

        fetch('https://dogsapi.origamid.dev/json/api/user', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                username,
                email,
                password
            })
        }).then(response => {
            console.log(response);
            return response.json();
        }).then(json => {
            console.log(json)
            return json;
        })
    }
```

Ainda estou digerindo tudo o que acontece nessa função, pois são várias coisas novas para mim que ainda não estão completamente assimiladas. A função toma como parâmetro um **event**, e utilizaremos o método preventDefault() para que a página não recarregue assim que clicarmos no botão "Enviar" (padrão do sistema).

O que vai acontecer em seguida?

utilizaremos um **fetch API**, buscando um link da API dogs da Origamid. Geralmente o fetch possui como método um GET. Aqui, isso ser mudado, e é por isso que passo um segundo parâmetro dentro dele, sendo eles:

1. o link
2. um objeto com as seguintes chaves:
    1. method: POST
    2. headers: {'Content-Type': 'application/json' (perceba que a chave aqui é utilizada com aspas, apenas por ela possuir um hífen. Por isso que as outras chaves não possuem aspas).
    3. body: precisamos transformar esse json em string, para podermos recuperar o username, email e password.

Como todo fetch é uma *Promise*, damos continuidade a ela utilizando o .*then,* primeiramente para puxar a resposta dessa *promise* e, em seguida, transformar a resposta em json para depois retornar o json.

## TOKENPOST

Agora passaremos para o próximo componente: o **TokenPost.js**, que servirá para criar um token único por usuário, destinado à autenticação do mesmo dentro do aplicativo, para que ele possa realizar posts. Você precisa estar logado e autenticado para realizar posts.

Dentro desse componente, teremos 3 elementos reativos:

```jsx
const [username, setUsername] = React.useState('')
    const [password, setPassword] = React.useState('')
    const [token, setToken] = React.useState('')
```

Percebam que aqui só precisarei do username e password para gerar o token. Não vamos precisar do e-mail novamente.

Na parte return temos o seguinte código:

```jsx
 <form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="username"
                value={username}
                onChange={({ target }) => setUsername(target.value)}
            />
            <input
                type="password"
                placeholder="password"
                value={password}
                onChange={({ target }) => setPassword(target.value)}
            />

            <button>Enviar</button>
            <p style={{ wordBreak: 'break-all' }}>{token}</p>
        </form>
```

Esse código vai puxar uma função (sobre a qual já vou falar sobre), e ela vai principalmente nos retornar um token único, algo que se assemelha com a seguinte string:

```jsx
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvZG9nc2FwaS5vcmlnYW1pZC5kZXYiLCJpYXQiOjE2MDMxOTc3MTYsIm5iZiI6MTYwMzE5NzcxNiwiZXhwIjoxNjAzMjg0MTE2LCJkYXRhIjp7InVzZXIiOnsiaWQiOiIxMjI4In19fQ.O9olTim21nnR42TY0RGve-CBUo_GswCAnC3LMN7QYys
```

Para fins de estudo, criamos esse <p> no final do formulário apenas para facilitar o copiar e colar do token para os próximos passos. Note que inserimos dentro desse <p> um *style* para dizer a esse token de ser quebrado, pois, por ser muito longo, acaba  criando uma barra horizontal no scroll e dificultando a navegação (ele corta no meio da string). Não conhecia esse estilo CSS.

Vamos agora falar da função handleSubmit() dentro desse componente:

```jsx
function handleSubmit(event) {
        event.preventDefault();

        fetch('https://dogsapi.origamid.dev/json/jwt-auth/v1/token', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({
                username,
                password
            })
        }).then(response => {
            console.log(response);
            return response.json();
        }).then(json => {
            console.log(json)
            setToken(json.token)
            return json;
        })
    }
```

O que fizemos aqui?

Novamente ela possui um fetch, mas dessa vez com outro link da api: o link que vai nos gerar o token. Utilizamos novamente o método POST, com headers de Content-Type application/json, para podermos puxar no body o username e password do usuário.

Em seguida temos os .then, que já são esperados em uma promise, mas repare que no último then, puxamos o token via o json.token e colocamos ele dentro do elemento reativo **setToken**, par que ele seja modificado imediatamente e que possamos conseguir acessar a esse token dentro da constante token, que foi declarada mais acima.

## PHOTOPOST

 

Ao longo desse post, vou percebendo que muitas coisas se repetem nesse componentes, e estou passando a entender melhor o que acontece.

Dentro do componente PhotoPost.js, o intuito é de poder postar uma foto do seu cachorrinho, atribuindo a ela:

nome

idade

peso

foto (em formato de arquivo)

```jsx
const [token, setToken] = React.useState('');
const [nome, setNome] = React.useState('');
const [peso, setPeso] = React.useState('');
const [idade, setIdade] = React.useState('');
const [img, setImg] = React.useState('');
```

Mais uma vez usamos os elementos reativos que serão modificados de forma dinâmica.

Dentro do return deste componente, temos o seguinte código:

```jsx
<form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="token"
                value={token}
                onChange={({ target }) => setToken(target.value)}
            />
            <input
                type="text"
                placeholder="nome"
                value={nome}
                onChange={({ target }) => setNome(target.value)}
            />
            <input
                type="text"
                placeholder="peso"
                value={peso}
                onChange={({ target }) => setPeso(target.value)}
            />
            <input
                type="text"
                placeholder="idade"
                value={idade}
                onChange={({ target }) => setIdade(target.value)}
            />
            <input
                type="file"
                onChange={({ target }) => setImg(target.files[0])}
            />
            <button>Enviar</button>
        </form>
```

Uma coisa que não falei anteriormente mas gostaria de deixar registrado, é que estou gostando muito de trabalhar com JSX, que é uma sintaxe semelhante ao XML, na qual você consegue escrever e compreender de uma melhor forma como será montado o seu component na UI. Vejam [esse post sobre o assunto](https://medium.com/reactbrasil/jsx-de6f43b06f41#:~:text=Em%20resumo%2C%20JSX%20%C3%A9%20uma,o%20seu%20component%20na%20UI.&text=Ao%20contr%C3%A1rio%20do%20passado%2C%20em,permite%20colocar%20HTML%20em%20JavaScript.).

Esse formulário segue a mesma lógica dos outros, com a diferença para o *input* de imagem, que não possui *placeholder* e nem *value*. Além disso, ele não toma como argumento o *target.value*, como os outros inputs, mas sim, o target.files[0].

Agora declaramos a função handleSubmit():

```jsx
function handleSubmit(event) {
        event.preventDefault();

        const formData = new FormData();
        formData.append('img', img)
        formData.append('nome', nome)
        formData.append('peso', peso)
        formData.append('idade', idade)

        fetch('https://dogsapi.origamid.dev/json/api/photo', {
            method: 'POST',
            headers: {
                Authorization: 'Bearer ' + token,
            },
            body: formData,
        }).then(response => {
            console.log(response);
            return response.json();
        }).then(json => {
            console.log(json)
            return json;
        })
    }
```

Quais são as diferenças dessa função para as anteriores? Observemos:

Primeiramente,  declaramos uma constante chamada formData. Eu não conhecia, então encontrei a seguinte definição:

> Um elemento HTML <form> — quando especifico, o objeto FormData será preenchido com as chaves/valores atuais do formulário usando a propriedade name de cada elemento para as chaves e seu valor enviado para os valores. Também condificará conteúdo de entrada do arquivo.

Você poderia adicionar uma chave/valor usando FormData.append. E é isso que é feito na sequência desse código. ele insere a key, e em seguida o elemento reativo (ou seja, sem as aspas, para buscar o valor da constante inserida pelo usuário (e modificada pelo useState)).

Em seguida, realizamos novamente um fetch, e desta vez o *headers* possuirá um conteúdo diferente, ou seja, um "Authorization: 'Bearer ' + token". Nunca tinha ouvido falar sobre Bearer Authentication, então fui na internet pesquisar o que era. encontrei [isto](https://swagger.io/docs/specification/authentication/bearer-authentication/).

> Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer tokens. The name “Bearer authentication” can be understood as “give access to the bearer of this token.” **The bearer token is a cryptic string, usually generated by the server in response to a login request**. **The client must send this token in the Authorization header when making requests to protected resources.**

O final dessa frase explicou bem para que serve o Authorization: Bearer.

Em seguida, temos todos os thens, como se é esperado de uma promise, retornando o nosso json.

## PHOTOGET

Agora vamos para o último endpoint, o PHOTOGET.

Ele servirá para buscarmos uma foto a partir de um certo ID. Para isso, precisaremos declarar uma constante id, usanto o useState novamente.

```jsx
const [id, setId] = React.useState('');
```

O retorno desse componente será o seguinte:

```jsx
<form onSubmit={handleSubmit}>
  <input type="text" value={id} onChange={(target) => setId(target.value)} />
  <button>Enviar</button>
</form >
```

Nada de novo aqui, estamos seguindo os mesmos passos dos outros componentes endpoint.

Agora vamos à nossa função de handleSubmit()

```jsx
function handleSubmit(event) {
        event.preventDefault();

        fetch(`https://dogsapi.origamid.dev/json/api/photo/${id}`)
            .then((response) => {
                console.log(response);
                return response.json();
            })
            .then((json) => {
                console.log(json);
                return json;
            });
    }
```

Reparem no *fetch* aqui, como ele é feito dessa vez.

Como queremos buscar o **id** de uma foto específica de algo que foi postado anteriormente, utilizaremos uma **string literal**  dentro do fetch para podermos acessar à **id** dentro da string na qual está o link para o fetch. Em seguida temos novamente os then, como esperado, para termos a resposta em formato json.

---

Esta foi a primeira parte do projeto Insta Doguinhos que estou realizando em React. Ficarei feliz com comentários e feedback de vocês! <3