I’m a Full Stack Software Engineer.
Enthusiast what is the best in web and mobile development! 🚀
🌎 Front-end Web with Next.JS/React
📲 Front-end Mobile with React Native
📡 Back-end with Nodejs/Nest.JS
🛠️ Typescript
🧰 And more...
Projeto desenvolvido na trilha de ReactJS no Ignite da Rockeseat! 🚀
Vamos mostrar na prática como obter o progresso de cada requisição HTTP sendo feita através do método POST, do front end para o back end utilizando o Axios.
Imagine que você tem um app front end que faz upload de arquivos para um servidor. Você quer acompanhar e mostrar ao usuário o progresso do envio desses arquivos, como no exemplo abaixo:
Isso é possível e fácil de implementar utilizando o Axios.
Vamos como codar essa funcionalidade.
Sintaxe básica:
// Utilizando axios
import axios from axios;
// Criando um FormData que armazena a imagem (arquivo)
const data = new FormData();
data.append("file", file, filename);
// Fazendo a requisição para o servidor com método POST
// Enviando o arquivo que está na variável data
// Passando um objeto de configuração que possui um método onUploadProgress
axios
.post("https://my.server.com/posts", data, {
onUploadProgress: (event) => {
let progress: number = Math.round(
(event.loaded * 100) / event.total
);
console.log(
`A imagem ${filename} está ${progress}% carregada... `
);
},
})
.then((response) => {
console.log(
`A imagem ${filename} já foi enviada para o servidor!`
);
})
.catch((err) => {
console.error(
`Houve um problema ao realizar o upload da imagem ${filename} no servidor AWS`
);
console.log(err);
});
Basicamente é realizado uma requisição do tipo POST utilizando o Axios, passando a variável data, com o arquivo. Passamos também um objeto com a configuração da requisição. Nele contém o método onUploadProgress que recebe um event, esse event contém as propriedades loaded e total.
loaded é o quanto já foi carregado e total armazena o tamanho total do arquivo.
Então é feito um cálculo de regra de três para definir a percentagem que já foi carregada no servidor. A variável progress armazena esses valores conforme a função onUploadProgress é executada automaticamente.
Como estamos lidando com uma Promises, no final da execução o método Then é executado e conseguimos informar que o arquivo já foi enviado.
Se houver algum erro, o método Catch é executado, assim podemos imprimir no log o erro.
Até aqui entendemos a lógica de como funciona o progresso do envio de arquivos.
No código abaixo vamos explorar um pouco mais sobre o assunto, mostrando um trecho de código que foi utilizado no exemplo de caso de uso.
import api from "../services/api";
export interface IFile {
id: string;
name: string;
readableSize: string;
uploaded?: boolean;
preview: string;
file: File | null;
progress?: number;
error?: boolean;
url: string;
}
const [uploadedFiles, setUploadedFiles] = useState<IFile[]>([]);
const updateFile = useCallback((id, data) => {
setUploadedFiles((state) =>
state.map((file) => (file.id === id ? { ...file, ...data } : file))
);
}, []);
const processUpload = useCallback(
(uploadedFile: IFile) => {
const data = new FormData();
if (uploadedFile.file) {
data.append("file", uploadedFile.file, uploadedFile.name);
}
api
.post("posts", data, {
onUploadProgress: (progressEvent) => {
let progress: number = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log(
`A imagem ${uploadedFile.name} está ${progress}% carregada... `
);
updateFile(uploadedFile.id, { progress });
},
})
.then((response) => {
console.log(
`A imagem ${uploadedFile.name} já foi enviada para o servidor!`
);
updateFile(uploadedFile.id, {
uploaded: true,
id: response.data._id,
url: response.data.url,
});
})
.catch((err) => {
console.error(
`Houve um problema ao fazer upload da imagem ${uploadedFile.name} no servidor AWS`
);
console.log(err);
updateFile(uploadedFile.id, {
error: true,
});
});
},
[updateFile]
);
Nesse código, o evento de onUploadedFile é executado seguindo a mesma lógica que explicamos anteriormente, o progresso será calculado e a função updateFile é chamada a cada update do evento, recebendo o id do arquivo enviado ao servidor e o progresso.
A função updateFile irá alterar o estado do arquivo em questão, passando o valor atual do progresso que irá refletir na tela com um Loading de progresso usando a lib react-circular-progressbar. Conforme vimos no vídeo do caso de uso acima.
Quando é finalizado o upload do arquivo, o método then é executado e invoca a função updateFile, passando o id fake do arquivo e um objeto que tem o id que o servidor gerou e a URL do arquivo que já foi salva no S3 da AWS.
Na tela vai aparecer um link excluir e um ícone representará que o arquivo foi enviado com sucesso!
Algum erro pode acontecer na execução, o servidor não permite arquivos maiores que 2 MB.
Se o usuário enviar um arquivo maior que o limite estabelecido no servidor, o método catch será executado. Então iremos alterar o estado do uploadedFile com um error: true que irá alterar o ícone no front end, indicando que o arquivo que está no preview não foi enviado por algum motivo — poderíamos colocar um tooltip para mostrar o log do erro no componente ;)
E temos aqui o resultado esperado:
Imagem sendo enviados ao servidor, um deu erro, três estão sendo enviados e quatro foram enviados com sucesso! Nessa imagem podemos observar o progresso de cada envio 🚀
Objetivo foi mostrar essa funcionalidade bacana do Axios de ouvir o evento de envio de arquivos e mostrar a quantidade em percentual do processamento do envio, com isso podemos mostrar um loading bem legal.
Conseguimos melhorar a experiência do usuário mostrando o progresso do envio arquivo.
O objetivo não foi mostrar o fluxo completo do front end, isso vai ficar para um próximo post. Mas para não te deixar na curiosidade, indiquei um vídeo logo abaixo que é para você aprender toda a lógica dessa implementação!
Conhecendo o Axios
Criando um Back End em Node.js para envio de arquivos no S3 da AWS
E aí, o que achou do post?
Espero que tenha curtido! 💜
O aprendizado é contínuo e sempre haverá um próximo nível! 🚀
React é uma das bibliotecas de front-end mais apreciadas pela comunidade de desenvolvedores. Junto com o React, os termos como DOM Virtual, Componentes Funcionais, Gestão de Estado e Componentes de Ordem-Superior (Higher-Order Components). Entre esses termos, a Gestão de Estado desempenha um papel vital.
O gerenciamento de estado é um dos principais fatores que precisam ser considerados antes de iniciar um projeto React. Os desenvolvedores usam padrões e bibliotecas famosas como Flux, Redux e Mobx para gerenciar o estado em React. No entanto, eles adicionam complexidade e código boilerplate ao seus aplicativos.
Neste artigo, vamos discutir como o React Query aborda o problema mencionado acima, criando um pequeno aplicativo pokemon e mergulhando em seus conceitos-chave.
Dica: Compartilhe seus componentes reutilizáveis entre projetos usando Bit (veja no GitHub). O Bit simplifica o compartilhamento, a documentação e a organização de componentes independentes de qualquer projeto.
Podemos usá-lo para maximizar a reutilização de código, colaboração em componentes independentes e criar aplicativos escaláveis.
O Bit suporta Node, TypeScript, React, Vue, Angular e muito mais.
React Query é uma das ferramentas de gerenciamento de estado que tem uma abordagem diferente do Flux, Redux e Mobx. Ele apresenta os principais conceitos de Estado-do-Cliente e Estado-do-Servidor. Isso torna o React Query uma das melhores bibliotecas para gerenciar estado, já que todos os outros padrões de gerenciamento de estado tratam apenas do estado do cliente e acham difícil lidar com o estado do servidor que precisa ser buscado, ouvido ou inscrito.
Além de lidar com o estado do servidor, ele funciona incrivelmente bem, sem precisar de configurações customizadas, e pode ser personalizado de acordo com o seu gosto conforme o crescimento do seu aplicativo.
Vamos ver isso na prática usando alguns exemplos.
Em primeiro lugar, vamos instalar a React QUery dentro de um projeto React:
npm install react-query react-query-devtools axios --save
Ou:
yarn add react-query react-query-devtools axios
O React Query também tem suas próprias ferramentas de desenvolvimento, que nos ajudam a visualizar o funcionamento interno do React Query. Vamos configurar as ferramentas de desenvolvimento do React Query no arquivo App.js:
import { ReactQueryDevtools } from "react-query-devtools";
function App() {
return (
<>
{/* Os outros componentes da nossa aplicação */}
<ReactQueryDevtools initialIsOpen={false} />
</>
);
}
Quando configuramos as ferramentas de desenvolvimento do React Query, você pode ver o logotipo do React Query na parte inferior esquerda do seu aplicativo, assim:
O devtools nos ajuda a ver como o fluxo de dados acontece dentro do aplicativo, assim como Redux Devtools. Isso realmente ajuda a reduzir o tempo de depuração do aplicativo.
Assim como o GraphQL, o React Query também se baseia em conceitos básicos semelhantes, como
Neste exemplo, vamos usar a PokéApi. Começaremos com useQuery, que recebe uma chave única e uma função responsável por buscar dados:
import React from "react";
import axios from "axios";
import { useQuery } from "react-query";
import Card from "./Card";
const fetchPokemons = async () => {
const { data } = await axios.get("https://pokeapi.co/api/v2/pokemon/?limit=50");
return data;
};
function Main() {
const { data, status } = useQuery("pokemons", fetchPokemons);
const PokemonCard = (pokemons) => {
return pokemons.results.map((pokemon) => {
return <Card key={pokemon.name} name={pokemon.name}></Card>;
});
};
return (
<div>
{status === "loading" && <div>Loading...</div>}
{status === "error" && <div>Error fetching pokemons</div>}
{status === "success" && <div>{PokemonCard(data)}</div>}
</div>
);
}
export default Main;
O código acima irá renderizar uma UI como abaixo:
Como você pode ver, useQuery retorna os dados e o status que podem ser usados para exibir componentes de “Carregando…”, mensagens de erro e os dados reais. Por padrão, React Query só solicitará dados quando eles estiverem desatualizados ou antigos.
O React Query armazena os dados em cache para não renderizar os componentes, a menos que haja uma alteração. Também podemos usar alguma configuração especial com useQuery para atualizar os dados em segundo plano.
const {data, status} = useQuery ("pokemons", fetchPokemons, {staleTime: 5000, cacheTime: 10});
A configuração acima fará com que o React Query busque dados a cada 5 segundos em segundo plano. Também podemos definir um cacheTime e um retryTime que define o tempo que o navegador deve manter o cache e o número de tentativas em que ele deve buscar dados.
O React Query buscará dados assim que os dados / cache estiverem desatualizados. Isso acontece quando o staleTime padrão é passado. Você também pode invalidar o cache de maneira programática para que o React Query atualize os dados.
Para fazer isso, use queryCache. É uma instância utilitária que contém muitas funções que podem ser usadas para manipular ainda mais as Query e invalidar o cache.
queryCache.invalidateQueries("pokemons");
Também podemos passar variáveis para a query. Para isso, precisamos transmiti-los como um array.
const { data, status } = useQuery(["pokemons",75], fetchPokemons);
O primeiro elemento será a chave e o resto dos elementos são variáveis. Para usar a variável, vamos fazer algumas modificações em nossa função fetchPokemons.
const fetchPokemons = async (key,limit) => {
const { data } = await axios.get(`https://pokeapi.co/api/v2/pokemon/?limit=${limit}`);
return data;
};
As mutações são normalmente usadas para criar / atualizar / excluir dados ou executar efeitos colaterais do lado do servidor. O React Query fornece o hook useMutation para realizar mutações. Vamos criar uma mutação para criar um pokémon:
import React from "react";
import { useQuery } from "react-query";
function Pokemon() {
const [name, setName] = useState("");
const [mutateCreate, { error, reset }] = useMutation(
(text) => axios.post("/api/data", { text }),
{
onSuccess: () => {
setName("");
},
}
);
return (
<div>
<form
onSubmit={(e) => {
e.preventDefault();
mutateCreate(name);
}}
>
{error && <h5 onClick={() => reset()}>{error}</h5>}
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<br />
<button type="submit">Create Pokemon</button>
</form>
</div>
);
}
export default Pokemon;
Neste exemplo, quando adicionamos um novo nome de Pokémon e clicamos no botão Criar Pokémon , ele fará a mutação e irá buscar os dados. Se a mutação falhar, o erro será exibido.
O erro e o estado dos dados podem ser eliminados usando a função reset, que reinicializará a mutação. A função onSuccess pode ser usada para limpar o estado da entrada ou do nome.
Uma mutação tem mais propriedades como onSuccess, isIdle , isLoading , isError , isSuccess. Eles podem ser usados para lidar com erros e exibir informações relevantes para diferentes estados da mutação.
O React Query é uma das melhores maneiras de buscar, armazenar em cache e atualizar dados remotos. Precisamos apenas dizer à biblioteca onde você precisa buscar os dados, e ela tratará do cache, das atualizações em segundo plano e da atualização dos dados sem nenhum código ou configuração extra.
Ele também fornece alguns hooks e eventos para mutação e query para lidar com erros e outros estados dos efeitos colaterais, o que remove a necessidade de usar hooks como useState e useEffect e os substitui por algumas linhas com React Query.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.