ky
ky copied to clipboard
Improve Error Handling for Better Integration with React Query
Improve Error Handling for Better Integration with React Query
Current Behavior
Currently, when an error occurs in a Ky request, the error object contains a promise that needs to be resolved to access the error details. This differs from Axios, where error details are immediately available in the error.response.data
property.
This difference creates challenges when using Ky with libraries like React Query, especially when trying to render error messages immediately after a failed mutation.
Desired Behavior
It would be beneficial if Ky could provide immediate access to parsed error information, similar to Axios. This would allow for more straightforward error handling and rendering in React applications, particularly when used with React Query.
Example of Current Issue
Consider this example using React Query with Axios:
import { useMutation } from '@tanstack/react-query';
import axios from 'axios';
function MyComponent() {
const { mutate, isError, error, reset } = useMutation({
mutationFn: (data) => axios.post('https://api.example.com/data', data),
});
return (
<div>
<button onClick={() => mutate({ some: 'data' })}>Submit</button>
{isError && (
<Alert severity="error" onClose={reset}>
{error.response?.data.message}
</Alert>
)}
</div>
);
}
In this Axios example, error.response.data.message
is immediately available for rendering.
Now, let's look at the same example using Ky:
import { useMutation } from '@tanstack/react-query';
import ky from 'ky';
import { useState } from 'react';
function MyComponent() {
const [error, setError] = useState(null);
const { mutate, isError, reset } = useMutation({
mutationFn: (data) => ky.post('https://api.example.com/data', { json: data }).json(),
onError: async (error, variables, context) => {
if (error.response) {
// Await the json response from the error
const jsonError = await error.response.json();
setError(jsonError); // Save the error to state
} else {
setError({message: 'An unexpected error occurred'});
}
}
});
return (
<div>
<button onClick={() => { mutate({ some: 'data' }); reset(); }}>Submit</button>
{isError && error && (
<Alert severity="error" onClose={() => { reset(); setError(null); }}>
{error.message}
</Alert>
)}
</div>
);
}
In this Ky example, error.response.json()
is a promise, so error.response?.data.message
is not immediately available. We would need to await the promise before we can access the error details and create new state with errors, which complicates the rendering process.
Additional Complexity
The current Ky implementation adds further complexity because the promise represents not just the response, but also the request. This means that in some scenarios, we might need to call .json()
twice: once for sending the request and once for parsing the error.request.json()
Proposed Solution
One possible solution could be to automatically parse the error response and make it immediately available, similar to Axios. For example:
ky.post('https://api.example.com/data', { json: data })
.json()
.catch(error => {
if (error instanceof HTTPError) {
const responseData = await error.response.json();
throw {
...error,
response: {
data: responseData,
status: error.response.status,
statusText: error.response.statusText,
},
};
}
throw error;
});
This would allow Ky to behave more like Axios in error scenarios, making it easier to use with React Query and similar libraries. But when developing this option, it requires creating a new error class to type react-query correctly and writing additional code.
Questions for Consideration
- Is it feasible to change Ky's error handling to more closely match Axios's behavior?
- Could Ky provide an option to automatically parse error responses and make them immediately available?
Thank you for considering this enhancement. It would greatly improve the developer experience when using Ky, especially in React applications with React Query.