注册时触发Redux Toolkit非序列化值错误,求解决方案
注册功能Redux非序列化值报错排查解决
问题描述
在使用React 18、Node.js 16及Redux Toolkit开发注册功能时,点击注册按钮触发如下报错:
react_devtools_backend.js:4026 A non-serializable value was detected in an action,路径为
payload.config.adapter
报错原因
- 错误对象包含不可序列化数据:注册请求失败时,异步thunk中返回了完整的Axios
error.response对象,其中config.adapter是一个函数,属于非序列化值,违反了Redux对action payload必须可序列化的要求。 - 错误处理未过滤非序列化内容:Axios拦截器直接抛出完整错误对象,包含大量不可序列化属性,最终被传递到Redux action中。
修复步骤
1. 仅传递可序列化错误数据到Redux
修改authSlice.js中的异步thunk,在rejectWithValue中只提取后端返回的可序列化错误信息:
export const signUp = createAsyncThunk( 'auth/signUp', async (data, { rejectWithValue }) => { try { const result = await authAPI.register(data) return result } catch (error) { // 仅提取后端返回的错误数据,避免传递Axios完整响应对象 return rejectWithValue(error.response?.data || '注册失败') } } ) export const login = createAsyncThunk( 'auth/login', async (data, { rejectWithValue }) => { try { return await authAPI.login(data) } catch (error) { return rejectWithValue(error.response?.data || '登录失败') } } )
同时更新slice的rejected处理逻辑,确保存储的错误是可序列化的:
[signUp.rejected]: (state, { payload }) => { state.loading = false // 将错误转换为字符串或纯对象,避免存储非序列化值 state.error = typeof payload === 'string' ? payload : payload.message || '注册失败' },
2. 优化Axios错误拦截器(推荐)
修改axiosClient.js的响应拦截器,在错误时仅抛出可序列化的错误信息:
axiosClient.interceptors.response.use( (response) => { if (response && response.data) { return response.data } return response }, (error) => { // 提取可序列化的错误数据,抛弃Axios自带的非序列化属性 const errorInfo = error.response?.data || { message: '请求失败' } throw errorInfo } )
3. 调整Redux Store序列化检查(可选)
如果上述修复后仍有警告,可以在store配置中忽略特定action的序列化检查:
export const store = configureStore({ reducer: persistedReducer, middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: { ignoredActions: [ FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER, 'auth/signUp/rejected', 'auth/login/rejected' ], // 也可以忽略特定状态路径的检查 // ignoredPaths: ['auth.error'] }, }), })
额外提示:表单文件上传处理
当前注册表单包含avatar文件输入,但未处理文件上传逻辑。若需要实现头像上传,需修改submitForm构建FormData:
const submitForm = (data) => { data.email = data.email.toLowerCase() const formData = new FormData() // 遍历表单数据添加到FormData Object.entries(data).forEach(([key, value]) => { // 处理文件数组(react-hook-form返回的文件是数组) if (key === 'avatar' && value.length > 0) { formData.append(key, value[0]) } else { formData.append(key, value) } }) dispatch(signUp(formData)) }
同时在react-hook-form的register中配置支持文件:
<input type="file" name="avatar" accept="image/*" {...register('avatar')} className="..." />
内容的提问来源于stack exchange,提问作者Pavitar Sharma
相关产品推荐
相关产品推荐

