3

I have a component where I am fetching mock data. I am doing a query by using react-query with Suspense. I was following their docs. This is the component:

export const WorkHistory = () => {
    const { caseId } = useContext();
    const { api: mockApi } = useMockApi();
    const { data: workHistory } = mockApi.getWorkHistory(caseId.toString());

    return (
        <QueryErrorResetBoundary>
            {({ reset }) => (
                <ErrorBoundary
                    fallbackRender={({ error, resetErrorBoundary }) => (
                        <div>
                            There was an error! <Button onClick={() => resetErrorBoundary()}>Try again</Button>
                            <pre style={{ whiteSpace: "normal" }}>{error.message}</pre>
                        </div>
                    )}
                    onReset={reset}
                >
                    <Suspense
                        fallback={
                            <div className="flex justify-center">
                                <Loader size="3xlarge" title="Loading..." />
                            </div>
                        }
                    >
                        <WorkHistory workHistory={workHistory} />
                    </Suspense>
                </ErrorBoundary>
            )}
        </QueryErrorResetBoundary>
    );
};

And this is the getWorkHistory in mockApi:

const getWorkHistory = (caseId: string) =>
        useQuery({
            queryKey: `workHistory`,
            queryFn: (): Promise<WorkHistoryDto[]> => fakeFetch(JSON.parse(localStorage.getItem(`workHistory`))),
            staleTime: Infinity,
            suspense: true,
        });

const fakeFetch = (result): Promise<any> =>
        new Promise((resolve, reject) => {
            setTimeout(() => reject(new Error("fail")), 1000);
        });

But, this ErrorBoundary is not catching this error. I get this:

Uncaught Error: fail

What am I doing wrong here?

2 Answers 2

2

You are calling useQuery outside of the ErrorBoundary:

export const WorkHistory = () => {
    // ⬇️ useQuery is called here
    const { data: workHistory } = mockApi.getWorkHistory(caseId.toString());

    return (
        <QueryErrorResetBoundary>
            {({ reset }) => (
            // ⬇️ your ErrorBoundary starts here
                <ErrorBoundary
                  ...
                </ErrorBoundary>
            )}
        </QueryErrorResetBoundary>
    );
};

The useQuery call is what throws the error to the nearest ErrorBoundary, so it has to be inside the ErrorBoundary, not above it.


unrelated, but still important: You are violating the rules of hooks by calling useQuery inside a function called getWorkHistory. Hooks must be called in functional components or other hooks, so you would need to name that function useWorkHistory or useGetWorkHistory.

Sign up to request clarification or add additional context in comments.

Comments

0

I am not sure but I think Error Boundary is not able to catch asynchronous errors according to this article: https://blog.logrocket.com/handling-javascript-errors-react-error-boundaries/

1 Comment

react-query catches the async errors and re-throws them during rendering so that error boundaries can catch them. it's a react-query feature to integrate with error boundaries.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.