A non-serializable value was detected
Redux Toolkit
でAPIサーバーで生成したファイルを取得しようとしたら上記のエラーが発生してハマったので対処方法を記しておきます。
Redux Toolkit
は基本的にAPIなどから取得したデータは全てシリアライズして Store
に保持する設計になっています。
ファイルのような巨大なバイナリデータはそもそもキャッシュの対象外なので Store
に値を渡さないような細工が必要になります。
サンプルコード
RTK Query
の queryfn を使って Store
に値を渡す前にファイルダウンロードを実行し、 Store
にはダミーデータを渡しています。
const downloadFile = (blob, fileName) => {
const elm = document.createElement('a');
const url = window.URL || window.webkitURL;
const fileUrl = url.createObjectURL(blob);
elm.href = fileUrl;
elm.target = '_blank';
elm.download = fileName;
elm.click();
};
export const downloadFileApi = apiBase.injectEndpoints({
endpoints: (builder) => ({
downloadFile: builder.mutation({
queryFn: async (params, api, extraOptions, baseQuery) => {
const result = await baseQuery({
url: '/something/file',
method: 'POST',
body: params.apiParams,
responseHandler: ((response) => response.blob())
})
downloadFile(result.data, params.fileName);
return { data: null };
}
}),
}),
});
export const {
useDownloadFileMutation
} = downloadFileApi;
上記のAPIクライアントの呼び出し側の実装は以下のようになります。
const [downloadPdf] = useDownloadPdfMutation();
const downloadAction = () => {
const params = {
apiParams: { }, // 略
fileName: 'hoge'
};
downloadPdf(params);
};
参考サイト
以下のリンク先のIssueのコードを参考にしています、感謝!