Consolidate query error handling

This commit is contained in:
april 2024-01-04 14:13:07 -06:00
parent 783bf668d1
commit a600cff6e6
4 changed files with 35 additions and 78 deletions

View File

@ -12,10 +12,16 @@ import {
Scripts, Scripts,
ScrollRestoration, ScrollRestoration,
isRouteErrorResponse, isRouteErrorResponse,
useNavigate,
useRouteError, useRouteError,
} from "@remix-run/react"; } from "@remix-run/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import {
MutationCache,
QueryCache,
QueryClient,
QueryClientProvider,
} from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { import {
@ -30,6 +36,8 @@ import {
import { IconRocket } from "@tabler/icons-react"; import { IconRocket } from "@tabler/icons-react";
import { AuthProvider } from "./util/auth"; import { AuthProvider } from "./util/auth";
import { useState } from "react";
import { AxiosError } from "axios";
export const links: LinksFunction = () => [ export const links: LinksFunction = () => [
{ {
@ -94,9 +102,32 @@ export function ErrorBoundary() {
); );
} }
const queryClient = new QueryClient(); export default function App({ pageProps }) {
const navigate = useNavigate();
const [queryClient] = useState(
() =>
new QueryClient({
queryCache: new QueryCache({
onError: (error: Error) => {
if (error instanceof AxiosError && error.response?.status === 401) {
navigate("/login");
}
},
}),
defaultOptions: {
queries: {
staleTime: 1000,
retry: (failureCount, error: Error) => {
return (
!error ||
(error instanceof AxiosError && error.response?.status !== 401)
);
},
},
},
})
);
export default function App() {
return ( return (
<html lang="en"> <html lang="en">
<head> <head>

View File

@ -1,11 +1,8 @@
import { client } from "@/util/api"; import { client } from "@/util/api";
import { useAuth } from "@/util/auth";
import { Center, Container, List, Loader, Stack, Text } from "@mantine/core"; import { Center, Container, List, Loader, Stack, Text } from "@mantine/core";
import { useNavigate, useParams } from "@remix-run/react"; import { useParams } from "@remix-run/react";
import { IconAlertTriangle } from "@tabler/icons-react"; import { IconAlertTriangle } from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { AxiosError } from "axios";
import { useEffect } from "react";
export default function Flight() { export default function Flight() {
const params = useParams(); const params = useParams();
@ -14,25 +11,8 @@ export default function Flight() {
queryKey: [params.id], queryKey: [params.id],
queryFn: async () => queryFn: async () =>
await client.get(`/flights/${params.id}`).then((res) => res.data), await client.get(`/flights/${params.id}`).then((res) => res.data),
retry: (failureCount, error: AxiosError) => {
return !error || error.response?.status !== 401;
},
}); });
const navigate = useNavigate();
const { clearUser } = useAuth();
useEffect(() => {
if (
flight.isError &&
flight.error instanceof AxiosError &&
flight.error.response?.status === 401
) {
clearUser();
navigate("/login");
}
}, [flight]);
return ( return (
<Container> <Container>
<Stack h="calc(100vh - 95px)"> <Stack h="calc(100vh - 95px)">

View File

@ -1,5 +1,4 @@
import { client } from "@/util/api"; import { client } from "@/util/api";
import { useAuth } from "@/util/auth";
import { FlightConciseSchema } from "@/util/types"; import { FlightConciseSchema } from "@/util/types";
import { import {
NavLink, NavLink,
@ -13,8 +12,6 @@ import {
import { Link, useLocation, useNavigate } from "@remix-run/react"; import { Link, useLocation, useNavigate } from "@remix-run/react";
import { IconPlus } from "@tabler/icons-react"; import { IconPlus } from "@tabler/icons-react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { AxiosError } from "axios";
import { useEffect } from "react";
export function FlightsList() { export function FlightsList() {
const location = useLocation(); const location = useLocation();
@ -23,24 +20,9 @@ export function FlightsList() {
const flights = useQuery({ const flights = useQuery({
queryKey: ["flights-list"], queryKey: ["flights-list"],
queryFn: async () => await client.get(`/flights`).then((res) => res.data), queryFn: async () => await client.get(`/flights`).then((res) => res.data),
retry: (failureCount, error: AxiosError) => {
return !error || error.response?.status !== 401;
},
}); });
const navigate = useNavigate(); const navigate = useNavigate();
const { clearUser } = useAuth();
useEffect(() => {
if (
flights.isError &&
flights.error instanceof AxiosError &&
flights.error.response?.status === 401
) {
clearUser();
navigate("/login");
}
}, [flights]);
return ( return (
<Stack p="0" m="0" gap="0"> <Stack p="0" m="0" gap="0">
@ -82,24 +64,9 @@ export function MobileFlightsList() {
const flights = useQuery({ const flights = useQuery({
queryKey: ["flights-list"], queryKey: ["flights-list"],
queryFn: async () => await client.get(`/flights`).then((res) => res.data), queryFn: async () => await client.get(`/flights`).then((res) => res.data),
retry: (failureCount, error: AxiosError) => {
return !error || error.response?.status !== 401;
},
}); });
const navigate = useNavigate(); const navigate = useNavigate();
const { clearUser } = useAuth();
useEffect(() => {
if (
flights.isError &&
flights.error instanceof AxiosError &&
flights.error.response?.status === 401
) {
clearUser();
navigate("/login");
}
}, [flights]);
return ( return (
<Stack p="0" m="0" justify="space-between" h="calc(100vh - 95px)"> <Stack p="0" m="0" justify="space-between" h="calc(100vh - 95px)">

View File

@ -1,34 +1,13 @@
import { client } from "@/util/api"; import { client } from "@/util/api";
import { useAuth } from "@/util/auth";
import { Container, Text, Title } from "@mantine/core"; import { Container, Text, Title } from "@mantine/core";
import { useNavigate } from "@remix-run/react";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { AxiosError } from "axios";
import { useEffect } from "react";
export default function Me() { export default function Me() {
const user = useQuery({ const user = useQuery({
queryKey: ["user"], queryKey: ["user"],
queryFn: async () => await client.get(`users/me`).then((res) => res.data), queryFn: async () => await client.get(`users/me`).then((res) => res.data),
retry: (failureCount, error: AxiosError) => {
return !error || error.response?.status !== 401;
},
}); });
const { clearUser } = useAuth();
const navigate = useNavigate();
useEffect(() => {
if (
user.isError &&
user.error instanceof AxiosError &&
user.error.response?.status === 401
) {
clearUser();
navigate("/login");
}
}, [user]);
return ( return (
<Container> <Container>
<Title order={2}>{user.data.username}</Title> <Title order={2}>{user.data.username}</Title>