Search code examples
javascripttry-catchreact-query

Defining a variable inside the try block of the useQuery function (tanstack's react-query)


I encountered a weird issue where I couldn't define a variable inside an anonymous function which had a try catch block defined in it.

  let response: AxiosResponse<CustomType[]>;  // had to define outside the useQuery
  const { data: info } = useQuery(
    ['queryKey', a, b],
    async () => {
     // let response: AxiosResponse<CustomType[]>; //ERROR variable response is used before being assigned
      try {
        response = await getAxios().get(`requestURL`);
        const responseFiltered = {};
        response.data.forEach((a) => {
           responseFiltered[a] = a;
         })
        return responseFiltered;
      } catch (error) {
        logger.error({
          meta: { error, response}, // variable used here
        });
      }
    }
  );

Not sure why it expects the response variable to be defined outside the useQuery function.


Solution

  • You are telling the compiler that response will be of type AxiosReponse. However, you are not giving response a "value" in branches. response is assigned inside the try/catch, so in the catch clause, it might still be undefined. That's what TypeScript is trying to tell you.

    To fix this, define your response as being potentially undefined:

    let response: AxiosResponse<CustomType[]> | undefined
    

    Then you can use it in the catch block. Even though, very likely, in the catch block it will be undefined if the network request fails.

    With axios, the error is actually an AxiosError, which will contain the response, so maybe you'd want something like this?

    const { data: info } = useQuery(
        ['queryKey', a, b],
        async () => {
            try {
                const response = await axios.get(`requestURL`);
                return response;
            } catch (error) {
                if (axios.isAxiosError(error)) {
                    console.error({
                        meta: { error, response: error.response },
                    });
                }
                throw error
            }
        }
    );
    

    Please further keep in mind that catching an error just to log it is not ideal with react-query, because it "swallows" the error. You can see that I've re-thrown the error at the end of the catch block. A better approach would be to use the onError callback:

    const { data: info } = useQuery(
        ['queryKey', a, b],
        async () => {
            return await axios.get(`requestURL`);
        }, {
        onError: (error) => {
            if (axios.isAxiosError(error)) {
                console.error({
                    meta: { error, response: error.response },
                });
            }
        }
    })