React中axios错误API请求未输出catch日志 报poem.map非函数错误
问题根源
- 接口无匹配结果时不会触发axios的catch逻辑:你调用的诗词接口在查询不到对应内容时会返回200正常状态码,响应体是
{status:404, reason:"Not found"}格式的普通对象,而非预期的数组结构,也不会返回4xx/5xx错误状态码,因此axios不会进入catch分支,会直接把非数组的错误对象传入setPoemData。 - 页面崩溃的直接原因:
poem.map is not a function报错本质是调用map方法的目标不是数组类型。两种场景会触发该问题:一是poemData状态初始值没有设置为空数组,首次渲染时就是undefined/对象等非数组值;二是上面提到的接口返回错误对象被赋值给状态后,传入Viewer组件的poem是对象类型,调用map直接抛出运行时错误,导致React渲染树崩溃、页面白屏。 - 原有代码还存在两个隐藏问题:map循环渲染的元素没有加key属性会触发React警告;内部对
lines调用map时没有校验lines是否为数组,遇到异常数据会二次报错;map回调中条件不满足时会返回undefined,属于无效渲染逻辑。
修复方案
- 修正状态初始值
声明poemData状态时必须将初始值设为空数组,避免首次渲染就触发类型错误:const [poemData, setPoemData] = useState([]) - 补全接口响应的类型判断
在axios的then回调中先校验返回数据格式,非数组时按无结果逻辑处理,同时catch分支中也要重置状态,避免脏数据残留:const searchPoem= (event) => { if(event.key==="Enter") { axios.get(`https://poetrydb.org/${option}/${search}/all`) .then(res=>{ // 校验返回值是否为预期的数组格式 if (Array.isArray(res.data)) { setPoemData(res.data) } else { // 无结果时清空数据,可在此处添加用户提示逻辑 setPoemData([]) console.log('未查询到匹配内容', res.data) } }) .catch((err) => { // 请求出错时也要重置为安全的空数组 setPoemData([]) if (err.response) { console.log(err.response.data) console.log(err.response.status) console.log(err.response.headers) } else if (err.request) { console.log(err.request) } else { console.log('Error', err.message) } }) } } - 给Viewer组件增加类型兜底
组件内部先校验传入的poem是否为数组,同时对内部的lines字段也做类型校验,循环渲染补充唯一key,从渲染层彻底阻断崩溃可能:const Viewer=({poem})=>{ // 非数组格式直接返回空,不执行后续map逻辑 if (!Array.isArray(poem)) return null return( <> { poem.map((item, index) => { // 提前过滤结构不合法的item if (!item || item.author == null || item.title == null || !Array.isArray(item.lines)) { return null } const { author, title, lines } = item return( <div className="viewer" key={index}> <div className="author">{author}</div> <div className="title">{title}</div> <div className="lines"> {lines.map((line, lineIndex) => <div key={lineIndex}>{line}</div> )} </div> </div> ) }) } </> ) }
内容的提问来源于stack exchange,提问作者torrey pines
相关产品推荐
相关产品推荐

