Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommended way to redirect user to another page when useSuspenseQuery error occurs #108

Closed
tombryden opened this issue Oct 2, 2023 · 4 comments

Comments

@tombryden
Copy link

tombryden commented Oct 2, 2023

Hi,

Apologies for asking a question here, but how would you recommend handling this scenario?

User requests page EG: /page/1 with 1 being the ID to the page. 1 doesn't exist so returns a not found response from the API. I want to redirect the user to the 404 page preferably without /page/1 being rendered.

Additionally, what is the recommended way to handle network errors? I can create an error.tsx error boundary, however this displays a blank page while useSuspenseQuery attempts to refetch the data (is this expected behaviour?).

My solution to handle the first scenario (redirecting to 404) is below, however I am sure there must be a better way to handle this scenario:

export default function Page({
   params,
}: {
   params: { id: string };
}) {
   const { data, error } = useSuspenseQuery(
      GET_PAGE_QUERY,
      {
         variables: {
            id: params.id,
         },
         context: { fetchOptions: { cache: "no-store" } },
         errorPolicy: "all",
      }
   );

   const router = useRouter();

   useEffect(() => {
      if (error) {
         router.replace("/404");
      }
   }, [router, error]);

   return error ? (
      <Box mt={20}>Loading...</Box>
   ) : (
      <Box mt={20}>{data!.getPage!.id}</Box>
   );
}

Thanks

@tombryden tombryden changed the title Recommended way to redirect user to 404 page when useSuspenseQuery error occurs Recommended way to redirect user to another page when useSuspenseQuery error occurs Oct 2, 2023
@mvandergrift
Copy link

mvandergrift commented Oct 4, 2023

Can you put a redirect in the error.tsx file? Or is the issue the delay you're running into when the client attempts to refetch the data?

The default RetryLink makes 5 attempts to refetch in case of a network error. A 404 probably qualifies as a network error. You could add your own RetryLink to your chain to override this behavior, although it may not be what you want since the global retry behavior is desirable, esp. on sketchy connections. It looks like you could implement a custom strategy that continues to retry except for 404 errors.

Some good info on the RetryLink here https://www.apollographql.com/docs/react/api/link/apollo-link-retry/

@tombryden
Copy link
Author

tombryden commented Oct 7, 2023

It seems to redirect quickly to error.tsx (after one retry when a network error occurs) - thinking about it now, it probably does this due to the compiler being in dev mode. Prod probably redirects faster, but the question still remains, is it possible to redirect without hitting a useEffect as this shows a flash of the page in a loading state before redirecting to the 404 page. EG, in this network error scenario, it redirects to error.tsx, error.tsx renders, useEffect is hit then redirects to 404.

Many thanks for the info about RetryLink, but in terms of the 404 error from the API, that is my fault in explaining - I am still thinking in REST world.. apologies, updated my original post now. My GraphQL API returns 200 response but with a 'Not found' error message & classification so no refetching occurs, however the flash of the page in a loading state still occurs while the javascript is being injected (awaiting the useEffect to run).

The problem with putting a useEffect inside error.tsx will be the same, where the page will render, then redirect the user to the 404 page which functions, but isn't as clean as I would like it to be

@phryneas
Copy link
Member

phryneas commented Oct 9, 2023

I would assume that you could call redirect directly inside your component render function instead of a useEffect, in which case the component would never commit, but immediately redirect - but I'm honest, I'm guessing here.

@tombryden
Copy link
Author

I tried this initially, but the same thing occurred where the page rendered. Thinking about it now, perhaps this was due to being in dev mode so the page took some time to compile. I'm going to close this here as I believe running in prod will have the result I am after + got the clarification I was after about my method. Thanks for the help both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants