You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,属于无效渲染逻辑。
修复方案
  1. 修正状态初始值
    声明poemData状态时必须将初始值设为空数组,避免首次渲染就触发类型错误:
    const [poemData, setPoemData] = useState([])
    
  2. 补全接口响应的类型判断
    在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)
          }
        })
      }
    }
    
  3. 给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 19:51:19