Reputation: 400
I am trying to use RTK Query mutations to upload a file to the API. Here is my mutation code:
addBanner: builder.mutation({
query(body) {
return {
url: `/api/banners`,
method: 'POST',
body,
}
},
})
Here is how I generate the data for request.
const [addBanner, { isBannerLoading }] = useAddBannerMutation();
const new_banner = new FormData();
new_banner.append("file", my_file);
new_banner.append("type", my_type);
new_banner.append("title", my_title);
addBanner(new_banner).unwrap().then( () => ...
But I get an error:
A non-serializable value was detected in the state, in the path: `api.mutations.L-Mje7bYDfyNCC4NcxFD3.originalArgs.file`...
I know I can disable non-serializable check entirely through middleware, but I don't think it is an appropriate way of using Redux Toolkit and RTK. Without a file all works fine. Is there any right way of uploading files with RTK?
Upvotes: 14
Views: 29187
Reputation: 1228
There is one more way to upload file without hampering the payload i.e. without need to flatten the object and using FormData,
So basically, if need to send file along with other nested object, then we can do it by encoding
const convertFileToBase64 = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result); // Base64 string
reader.onerror = (error) => reject(error);
});
and call above function to convert the file into base64 in following way
await convertFileToBase64(selectedFile); // in my case selected file is in blob.
Upvotes: 0
Reputation: 104
pass formData
in the query.
Like this:
addBanner: builder.mutation({
query(body) {
return {
url: `/api/banners`,
method: 'POST',
body,
formData: true,
}
},
})
Upvotes: 0
Reputation: 44266
Edit: This has been fixed with @reduxjs/toolkit 1.6.1 - please update your package
I just opened an issue for this: https://github.com/reduxjs/redux-toolkit/issues/1239 - thanks for bringing it up!
For now, you'll probably have to disable that check (you can do so for a certain path in the state while keeping it for the rest with the ignoredPath option).
Upvotes: 8