GithubHelp home page GithubHelp logo

brunosllz / github-blog Goto Github PK

View Code? Open in Web Editor NEW
0.0 1.0 0.0 2.6 MB

Projeto desenvolvido na trilha de ReactJS no Ignite da Rockeseat! 🚀

HTML 1.97% JavaScript 2.80% TypeScript 94.92% CSS 0.31%
react-loading-skeleton react-query react-router-dom tailwindcss typescript vite

github-blog's Introduction

Hi, I'm Bruno

I’m a Full Stack Software Engineer.
Enthusiast what is the best in web and mobile development! 🚀

My current tools

🌎 Front-end Web with Next.JS/React
📲 Front-end Mobile with React Native
📡 Back-end with Nodejs/Nest.JS
🛠️ Typescript
🧰 And more...

💬 Find me elsewhere

Linkedin Badge Gmail Badge

github-blog's People

Contributors

brunosllz avatar

Watchers

 avatar

github-blog's Issues

Obtendo o status de progresso do envio de dados com Axios

Introdução

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.

Caso de uso

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.

Mensurando o Progresso de Upload na Prática

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 🚀

Conclusão

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!

Links

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! 🚀

Gerenciando estado remoto com React Query

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.

O que é React Query?

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.

Instalando o React Query

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

Configurando Ferramentas de Desenvolvimento

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

  • Query
  • Mutações
  • Invalidação de Query

Buscando Pokémons usando Query

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:

Cache no React Query

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.

Redefinindo o Cache com Invalidação de Query

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");

Variáveis no React Query

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;
};

Brincando com Mutações

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.

Conclusã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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.