React调用Unsplash API实现单图轮播时解构images[counter]报错如何解决
报错原因
- loading状态判断不严谨:你仅判断了请求中状态为loading,未处理请求成功但返回空数组的场景,此时
loading为false但images为空,images[counter]自然为undefined,解构直接失败 - 索引越界风险:后续做上下页切换时,如果counter值超过
images.length - 1或者小于0,都会导致取到的数组项为undefined - 额外隐藏问题:Unsplash接口返回的单条图片数据中,
urls是对象而非数组,你现有代码中的urls.map会直接抛出类型错误
可行实现方案
修复后的完整代码如下:
import React, { useEffect, useState } from "react"; import Loading from "./loading"; const key = "替换为你的Unsplash接口密钥"; const url = `https://api.unsplash.com/photos/?client_id=${key}`; function App() { const [loading, setLoading] = useState(true); const [images, setImages] = useState([]); const [counter, setCounter] = useState(0); const fetchImages = async () => { setLoading(true); try { const response = await fetch(url); const resData = await response.json(); // 先判断返回值是否为数组,避免非数组值导致后续逻辑出错 setImages(Array.isArray(resData) ? resData : []); } catch (error) { console.log(error); setImages([]); } finally { // 统一关闭loading,无论请求成功失败都不会一直显示加载中 setLoading(false); } }; useEffect(() => { fetchImages(); }, [url]); // 上一张切换逻辑,边界处循环跳转 const switchPrev = () => { setCounter(prev => prev <= 0 ? images.length - 1 : prev - 1); } // 下一张切换逻辑,边界处循环跳转 const switchNext = () => { setCounter(prev => prev >= images.length - 1 ? 0 : prev + 1); } if (loading) { return <main><Loading /></main>; } // 空数据兜底 if (!images.length) { return <main>暂无图片数据</main> } // 加兜底避免解构失败 const { id, created_at, description, urls } = images[counter] || {}; return ( <main> <div> <img src={urls?.full} alt={description || `图片${id}`} /> <p>发布时间:{created_at}</p> </div> <div> <button onClick={switchPrev}>上一张</button> <span>{counter + 1}/{images.length}</span> <button onClick={switchNext}>下一张</button> </div> </main> ); } export default App;
核心优化点:
- 接口返回值增加类型校验,避免非数组数据赋值给images
- 增加空数据兜底逻辑,无数据时直接返回提示不会触发后续报错
- 切换逻辑增加边界处理,counter不会出现超出数组索引范围的情况
- 深层属性访问增加可选链判断,避免属性不存在时抛出错误
- 适配Unsplash接口返回结构,直接取urls对象下对应尺寸的图片地址即可
内容的提问来源于stack exchange,提问作者Andrei Cristian Botea
相关产品推荐
相关产品推荐

