ReactJS使用fetch调用下载接口报Cannot read properties错误求助
排查方向
- 你贴出的代码中没有出现
payload字段,首先打开浏览器控制台的报错堆栈,定位到具体是哪一行代码在读取payload属性,确认该属性所属的对象为什么是undefined。 - 你标注为reducer实现的
printedPin函数不符合Redux reducer的规范:reducer必须是无副作用的纯函数,不能包含异步请求、DOM操作这类逻辑。你现在的写法是Redux Thunk异步action的逻辑,大概率是你错误地把它放在了reducer文件中,且没有按Thunk的规范编写、绑定,导致后续接收action的逻辑拿到的是undefined,读取payload时触发报错。 - 现有fetch请求的错误处理存在缺失:fetch只有在网络断连等极端情况才会抛错,接口返回4xx/5xx状态码时不会进入catch逻辑,你没有判断
response.ok就直接调用blob(),如果接口返回错误响应,后续处理逻辑可能拿到不符合预期的结果,引发报错。
修复方案
- 修正异步action的写法,按Redux Thunk规范调整
printedPin的实现,补全错误处理(该函数属于异步action,不应该放在reducer文件中,建议移到单独的action文件里):
export const printedPin = (id, callback) => async (dispatch) => { try { const requestUrl = `${apiUrl}/${id}/printpin` const response = await fetch(requestUrl) // 先判断请求状态是否正常 if (!response.ok) throw new Error(`请求失败,状态码:${response.status}`) const blob = await response.blob() if (blob.type === 'application/problem+json') { callback() // 如果需要派发错误action,确保payload字段存在 dispatch({ type: 'PRINT_PIN_ERROR', payload: { msg: '业务请求失败' } }) return } // 下载逻辑 const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = 'pin.pdf' a.click() window.URL.revokeObjectURL(url) // 释放对象URL占用的内存 dispatch({ type: 'PRINT_PIN_SUCCESS', payload: { success: true } }) } catch (err) { console.error('打印请求错误:', err) callback() dispatch({ type: 'PRINT_PIN_ERROR', payload: { msg: err.message } }) } }
- 调整reducer中的处理逻辑,访问payload前添加非空判断:
const initialState = { loading: false, success: false, error: null } export const pinReducer = (state = initialState, action) => { switch (action.type) { case 'PRINT_PIN_SUCCESS': // 使用可选链避免读取undefined的属性 return { ...state, success: action?.payload?.success ?? false, error: null } case 'PRINT_PIN_ERROR': return { ...state, error: action?.payload?.msg ?? '未知错误', success: false } default: return state } }
- 修正组件中调用异步action的方式,不要直接调用props里的函数,要通过dispatch触发:
import { useDispatch } from 'react-redux' import { printedPin } from '你的action文件路径' const YourComponent = () => { const dispatch = useDispatch() // 其他组件逻辑... const printPin = event => { event.preventDefault() // 把异步action传给dispatch,由Redux Thunk中间件处理执行 dispatch(printedPin(scePersonaEntity.perCod, activateAlert)) } // 渲染逻辑... }
内容的提问来源于stack exchange,提问作者Jack23
相关产品推荐
相关产品推荐

