
Conteúdo
- Motivação
 - Componente principal
 - Componente do Loader
 - Adicionando o Loader no componente principal
 - Função da chamada da API
 - Dados retornados
 - Código completo
 - Ao vivo
 
Motivação
No ultimo post que eu fiz mostrei como fazer um loader com CSS, esse post aqui:
Criando um loader simples com CSS.
Massa..... show de bola esse loader.... Mas eu fico só olhando pra ele rodando? Seria bom usar em alguma coisa mais "vida real" né? Tem como?
Yaaaaaas!
Então, para demonstrar isso, criei um projeto básico. Usei o create-react-app para iniciar o projeto.
O que eu quero para este projeto simples:
- Ter um input onde a pessoa pode inserir o nome do seu usuário do github;
 - Ter um botão que vai fazer uma chamada à API do github;
 - Mostrar o Loader enquanto é feita a requisição;
 - Mostrar os dados da pessoas que vieram da API do github.
 
Uma obs: da primeira vez que pega o usuário dá pra ver o loader e depois ele some. Se for testar com o mesmo usuário novamente, o loader não aparece mais (na vdd talvez rápido demais que não da pra ver).
Então.... LET'S DO IT! 👊🏽
Componente principal
Inicialmente no componente principal vamos ter um form e dentro dele colocamos:
- uma 
labelpara oinput; - o 
inputpara receber o nome do usuário; botãode submit.
import React, { useState } from 'react';
const App = () => {
  return (
    <div className="app">
      <form className="form-github-user">
        <label htmlFor="github-user" className="label-github-user">Digite seu usuário do Github:</label>
        <input type="text" id="github-user" className="input-github-user"/>
        <button type="submit" className="btn-submit">Enviar</button>
      </form>
    </div>
  );
}
export default App;
Componente do Loader
Depois criamos um componente para o Loader, pegando o código do post anterior. Ele tem somente uma div e CSS (só diminuí um pouco o tamanho dele e adicionei uma margem no topo):
Loader.js
import React from 'react';
import './Loader.css';
const Loader = () => {
    return (
        <div role="alert" className="loader"></div>
      );
}
export default Loader
Loader.css
.loader {
    width: 50px;
    height: 50px;
    border: 10px solid #eee;
    border-bottom-color: rebeccapurple;
    border-radius: 50%;
    animation: rotate 1.5s linear infinite;
    margin-top: 2rem;
  }
  
  @keyframes rotate {
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
  }
Adicionando o Loader no componente principal
E no componente principal fazemos algumas coisas:
- 
Importamos o
Loaderno componente principal. - 
Para o loader criamos uma variável
showLoaderpara poder lidar com a mudança uma mudança de estado, usando o hook useState().- O estado inicial da variável definimos o valor "false" com a função do 
useState(), o retorno dele são duas coisas: o valor do estado atual e uma função que permite que se atualize o valor; - Vamos usar ela para controlar a renderização do componente 
Loader. 
 - O estado inicial da variável definimos o valor "false" com a função do 
 - 
Para pegar o
usernameque vem do input também usamos o hook useState(); - 
Adicionamos um
onChangeno input para pegar o que foi digitado e inserir o valor nousernameusando osetUsername(); - 
E abaixo do
formcolocamos uma condicional que faz com que incialmente oLoadernão será renderizado (devido ao valor false que colocamos ). 
import React, { useState } from 'react';
import Loader from './components/Loader/Loader'
const App = () => {
  const [showLoader, setShowLoader] = useState(false)
	const [username, setUsername] = useState('')
  return (
    <div className="app">
      <form className="form-github-user">
        <label htmlFor="github-user" className="label-github-user">Digite seu usuário do Github:</label>
        <input type="text" id="github-user" className="input-github-user" onChange={e=>setUsername(e.target.value)}/>
        <button type="submit" className="btn-submit">Enviar</button>
      </form>
      {showLoader && <Loader/>}
    </div>
  );
}
export default App;
Função da chamada da API
Agora vamos criar uma função que será chamada quando houver o submit do form. Chamaremos a função de "handleForm":
- Antes da função criamos uma variável 
userDatapara poder armazenar os dados que vão retornar da API, usando o hook useState(). - Na função usamos o 
e.preventDefaultpara evitar um comportamento padrão, nesse caso só queremos evitar o comportamento padrão doform, esse comportamento padrão doformé o reload da página quando oformé submetido. Usando oe.preventDefaultconseguimos fazer com que a ação de submit doformfique de forma assíncrona só esperando a resposta; - Atualizamos o estado do 
showLoaderpara "true" (que na renderização vai fazer ele aparecer devido a condicional); - Usamos o fetch para fazer a requisição na API do Github, usando o "username" que vai ser preenchido no momento que a pessoa digita no input, e na url pegamos esse valor que foi inserido pela pessoa;
 - Após a resposta do 
fetch, no segundothennós pegamos os dados que vem como resposta (após ser transformado num json usando a o .json() no qual retorna uma promisse com o resultado); - E após colocar os dados retornados no 
setUserData()também mudamos o estado do loader de volta para "false" (que na renderização vai fazer ele sumir devido a condicional); 
Então é basicamente: mostra o loader enquanto pega os dados, após trazer os dados tira o loader;
const [userData, setUserData] = useState({})
const handleForm = (e) => {
    e.preventDefault();
    setShowLoader(true)
    fetch(`https://api.github.com/users/${username}`)
        .then(res => res.json())
        .then(data => {
          setUserData(data)
          setShowLoader(false)
        })
        .catch((err) => {
          console.log(err)
          setShowLoader(false)
        })
  }
E no form adicionamos o atributo onSubmit chamando a função acima, para que quando haja um click no botão de submit a função seja executada.
<form onSubmit={handleForm} className="form-github-user">
Dados retornados
E para vermos o que foi retornado, criamos um componente chamado "UserData" e exibimos os dados que vai vir das "props"
import React from 'react';
import './UserData.css';
const UserData = ({data}) => {
    return (
        <div className="user-data">
        <img src={data.avatar_url} alt={data.name}/>
        <table>
          <tbody>
            <tr>
              <td><strong>Name:</strong></td>
              <td>{data.name}</td>
            </tr>
            <tr>
              <td><strong>Localização:</strong></td>
              <td>{data.location}</td>
            </tr>
            <tr>
              <td><strong>Bio:</strong></td>
              <td>{data.bio}</td>
            </tr>
            <tr>
              <td><strong>Perfil criado em:</strong></td>
              <td>{data.created_at}</td>
            </tr>
          </tbody>
        </table>
      </div>
      );
}
export default UserData
E no componente principal, importamos esse componente e passamos os dados retornados para ele que foram preenchidos no setUserData para userData.
- Adicionamos o componente UserData para ser renderizado e passamos 
userDataapara o componente através da propdata; - No componente UserData temos a prop 
datae recebemos os dados através dela; 
import React, { useState } from 'react';
import Loader from './components/Loader/Loader'
import UserData from './components/UserData/UserData'
import './App.css';
const App = () => {
  const [showLoader, setShowLoader] = useState(false)
  const [username, setUsername] = useState('')
  const [userData, setUserData] = useState({})
  const handleForm = (e) => {
    e.preventDefault();
    setShowLoader(true)
    fetch(`https://api.github.com/users/${username}`)
        .then(res => res.json())
        .then(data => {
          setUserData(data)
          setShowLoader(false)
        })
        .catch((err) => {
					console.log(err)
          setShowLoader(false)
        })
  }
  return (
    <div className="app">
      <form onSubmit={handleForm} className="form-github-user">
        <label htmlFor="github-user" className="label-github-user">Digite seu usuário do Github:</label>
        <input type="text" id="github-user" className="input-github-user" onChange={e=>setUsername(e.target.value)}/>
        <button type="submit" className="btn-submit">Enviar</button>
      </form>
      {showLoader && <Loader/>}
      <UserData data={userData} />
    </div>
  );
}
export default App;
Código completo
Esse código pode ser melhorado, tentei deixa-lo simples.
O código completo está nesse repositório:
https://github.com/talitaoliveira/using-loader-wait-request-react
No projeto que está no repositório incrementei algumas coisas além do que está aqui. (ainda precisa ajeitar algumas coisas)
- Criei alguns testes
 - Tentei colocar uma mensagem de erro caso de algum problema na requisição
 - Dados são mostrados somente se o objeto 
userDataestiver preenchido (não fica mostrando a tabela vazia com "nome", "localização, "bio", "perfil criado em") - Também coloquei um workflow usando Github Actions, pra rodar os testes e se tudo tiver passando fazer o deploy para o gh-pages. Mostrei um pouco como fiz isso nesse post: CI/CD e Github Actions 😊
 
~🌟~
Bem.. é isso. 😉
Esse post era pra ter sido postado semana passada, mas por motivo de força maior (final de semana na praia com a família) não postei nada.
Preferi descansar, relaxar a mente... Passei por um momento não muito legal, e precisava desacelerar um pouco.
Mas está tudo bem agora, só preciso me manter mais "pé no chão". 🙃
Espero que este post possa ser útil para alguém 😊.
Até a próxima. 🤙🏽
Ao vivo
E pode ser visto aqui: https://talitaoliveira.github.io/using-loader-wait-request-react/