React.js中Cannot read 'map' of undefined报错与API重复请求问题排查
问题解答
第一个问题解决方案
你的判断是正确的,问题出在两个核心点:
- 初始值设置错误:你给
details设置的初始值是空数组[],但接口返回的是包含total_results、total_pages、results属性的对象,空数组不存在results属性,所以首次渲染时details.results就是undefined,调用map方法自然报错。 - 异步请求时机不对:你把axios请求直接写在组件函数体里,组件每渲染一次就会触发一次请求,在请求返回前,组件已经执行了渲染逻辑,此时还没调用
setDetails更新状态,自然拿不到返回数据。
修复步骤:
- 调整
details的初始值为符合返回结构的默认对象:
const [details, setDetails] = useState({ results: [], total_results: 0, total_pages: 0 });
- 将axios请求包裹在
useEffect钩子中,设置依赖项为query,只有当query变化时才重新发起请求:
useEffect(() => { axios.get("http://localhost:5000/results/" + query).then((response) => { setDetails(response.data); console.log(response.data); }); }, [query]);
- 渲染遍历的时候增加可选链判断,避免边界情况报错:
{details?.results?.map((result) => { // 原有渲染逻辑 })}
第二个问题解决方案
请求触发两次的原因通常有两个:
- 就是第一个问题里提到的,你把请求直接写在组件函数体中,组件每次重渲染都会重新执行请求逻辑,把请求移到
useEffect里就可以解决这个问题。 - 如果你使用的是React18及以上版本,开发环境下默认开启的严格模式
<StrictMode>会让组件挂载两次,用来检测副作用代码的问题,这个情况在生产环境会自动消失,不需要额外处理,如果要在开发环境关闭,可以移除根组件外的<StrictMode>标签。
分页适配注意点
你目前的分页逻辑存在参数重复拼接的问题,每次切换页码直接把&page=拼到原有query后面,多次切换后会出现query=xxx&page=1&page=2的异常参数。建议单独声明一个page状态存储当前页码,发起请求的时候再把query和page参数拼接,不要直接修改原搜索关键词的query值。
内容的提问来源于stack exchange,提问作者Alex Braga
相关产品推荐
相关产品推荐

