React Clean Code — Simule Cenários de Rede com Mirage.js
Em meu livro Reação sustentável , apresentei um recurso no qual trabalhei há algum tempo. Esse recurso é interessante de várias maneiras, e eu o selecionei porque envolve vários estados na exibição — que é um dos motivos pelos quais a construção da interface do usuário é complicada .
Eles não são estados típicos da interface do usuário, mas estados de cache do servidor, conforme descrito no artigo de Kent aqui . Todas as solicitações de rede podem dar errado, tempo limite, muitas solicitações ou até mesmo tempo de inatividade do serviço. Nas exibições, precisamos refletir esses status de rede de maneira correspondente.
status diferente
O recurso direto para inicializar aqui é que, quando o usuário chega à página no início, precisamos verificar o status atual de um pedido. Se estiver em andamento, precisamos mostrar um botão desativado I'm heree algumas mensagens de dicas. E em algum momento, quando o pedido estiver pronto para retirada, o botão precisa ser ativado para que possamos clicar nele para avisar a loja. Ao clicar no botão, uma notificação é enviada e o pedido é entregue direto no porta-malas do seu veículo. Além disso, se algo der errado, mostramos um número como alternativa para que possamos ligar para a loja por telefone.
Portanto, precisamos considerar pelo menos as seguintes coisas:
- Buscar dados do servidor
- Tente novamente se algo der errado na rede
- Tente novamente se os dados forem retornados, mas não o que queríamos
- Pare de tentar novamente quando falhamos muitas vezes
- Atualizar dados para o servidor
- Tratamento de erros para cada solicitação de rede
o caminho feliz
Podemos começar com o caminho feliz, pois é o passo mais fácil e a coisa mais importante que queremos garantir que aconteça.
No teste, o caminho feliz para (inicializado → pronto) pode ser descrito como:
Zombando do pedido de caminho feliz
No meu livro, usei mswcomo servidor de simulação e funcionou muito bem. Estou usando mirage.jsaqui para simplificar. Também gosto da parte de modelagem de dados da biblioteca. Não importa muito aqui, e você pode usar qualquer um deles .
Por exemplo, podemos definir uma getAPI para verificar o status do pedido no teste. Ele intercepta as requisições enviadas /api/orders/<id>e sempre retorna um objeto com readystatus.
import { createServer } from "miragejs";
const createMockServer = () => createServer({
routes() {
this.get("/api/orders/:id", (schema, request) => {
return {
id: request.params.id,
status: "ready",
};
});
}
})
describe("Direct To Boot", () => {
beforeEach(() => {
server = createMockServer();
})
afterEach(() => {
server.shutdown()
})
//...
});
Implementando busca com react-query
Em meu artigo anterior , discuti em detalhes quantas coisas triviais você precisa considerar para fazer uma solicitação de rede “simples”. Além de ser mais simples se você usar react-queryem vez de implementá-lo manualmente.
Para usar react-query, primeiro precisamos definir uma queryfunção. Observe aqui que, se res.data.statusnão for ready, ele gerará um erro. E react-querypode detectar esse erro e acionar um refetchse configurado.
const fetchOrder = (orderId: string) => {
return axios.get(`/api/orders/${orderId}`).then((res) => {
if (res.data.status === "ready") {
return res.data;
} else {
throw new Error("fetch error");
}
});
};
const useOrder = (orderId: string) => {
const [status, setStatus] = useState<string>("initialised");
useQuery(["fetchOrder"], () => fetchOrder(orderId), {
retry: 5,
onError: () => setStatus("error"),
onSuccess: () => setStatus("ready"),
});
return { status }
}
Simular um erro
Em mirage.js, simular um erro para o teste detectar é bastante simples. Também achei útil ter vários ids que disparariam erros para que você pudesse testar diferentes lógicas de tratamento de erros.
Por exemplo, podemos definir uma lista de ids que indicam erros quando usados.
this.get("/api/orders/:id", (schema, request) => {
if(['error-id', 'timeout-id'].includes(request.params.id)) {
return new Response(500, {}, {error: "something went wrong"});
}
return {
id: request.params.id,
status: "ready",
};
});
it("shows a fallback call the store button", async () => {
render(<DirectToBoot orderId="error-id"/>);
await waitFor(() =>
expect(
screen.getByText("Seems something went wrong...")
).toBeInTheDocument(), { timeout: 3000});
const button = screen.getByText("04 23 33");
await waitFor(() => expect(button).toBeInTheDocument(), {timeout: 3000})
});
Em nosso recurso, também queremos simular a long-runningordem para garantir que a interface do usuário não seja bloqueada pela busca inicial. Podemos simulá-lo definindo uma variável com initialisedestado e posteriormente usar um timer para atualizar o valor.
const longRunningOrder = {
id: 'long-running-order',
status: "initialised",
}
//...
const createMockServer = () => createServer({
routes() {
this.get("/api/orders/:id", (schema, request) => {
if(['long-running-order'].includes(id)) {
const timerId = setTimeout(() => {
longRunningOrder.status = 'ready'
clearTimeout(timerId);
}, 2000)
return longRunningOrder;
}
});
}
})
o código final
Tendo react-queryque lidar com toda a lógica relacionada à rede, como você pode imaginar o quão simples o Direct To Orderpróprio componente final pode ser simplificado.
export function DirectToBoot({ orderId }: { orderId: string }) {
const {status, notifyStore} = useOrder(orderId);
return (
<div className="container">
<h3>Direct to boot</h3>
<p>{getMessage(status)}</p>
<div className="buttonContainer">
{createButton(status, notifyStore)}
</div>
</div>
);
}
Estamos usando o gancho como uma máquina de estado, assim como o gráfico de estado que ilustramos no início do artigo.
Resumo
Neste artigo, discutimos como usar mirage.jspara simplificar a simulação de rede para casos impossíveis ou difíceis se você falar com APIs reais no código front-end. Vimos o caminho feliz, o tratamento de erros e as novas tentativas com mirage.js, e também como é fácil usá-lo react-querypara simplificar a lógica de implementação do código relacionado à rede.
Você pode encontrar o código-fonte completo deste artigo aqui. E se você preferir vídeos, publiquei no meu canal do YouTube em vídeos de 2 horas.
Se você gosta da leitura, por favor, inscreva-se na minha lista de e-mail . Compartilho técnicas de código limpo e refatoração semanalmente em blogs , livros e vídeos .





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)