为何在React中使用Fetch API时需检查返回数组长度?
为什么需要用
data.length > 0包裹异步获取数据的渲染代码? 这跟Fetch API是否失败完全没关系,核心是React组件的渲染时机和异步请求的时序问题,拆解下来是这么回事:
初始渲染时数据还没准备好
你给data设置的初始状态是空数组[],组件第一次渲染时,data就是这个空数组。这时候直接访问data[1].title,空数组的索引1对应的元素是undefined,自然会触发「无法读取undefined的title属性」的报错——跟请求成功与否无关,纯粹是第一次渲染时数据还没到位。Fetch是异步操作,不会阻塞组件渲染
组件挂载后useEffect才触发getData()发起请求,但网络请求需要时间完成。在请求返回结果、调用setData(myJson)更新状态之前,组件已经完成了第一次渲染。也就是说,组件先渲染一次(用初始空数组),等请求完成后才会基于新数据重新渲染。条件判断的作用是“挡掉”数据未就绪时的错误渲染
data.length > 0 && (...)这个逻辑是React里常用的“短路求值”技巧:当data.length > 0为假(也就是初始空数组的情况),后面的<Welcome>组件就不会被渲染,也就不会执行data[1].title这个会报错的代码。等请求完成,data被更新成接口返回的有效数组,长度大于0,条件成立,才会渲染<Welcome>,这时候data[1]已经是合法的对象,访问title就没问题了。
额外优化建议
- 可以用可选链操作符简化判断,即使
data[1]是undefined也不会报错:<Welcome text={"This data is from a JSON feed: " + (data[1]?.title || '数据加载中...')} /> - 也可以添加加载状态,提升用户体验:
const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const getData = () => { fetch('https://www.someplace.com/jsonfile', { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } }) .then(response => response.json()) .then(myJson => { setData(myJson); setLoading(false); }) .catch(() => { setLoading(false); // 处理请求失败的情况 }); } useEffect(() => { getData(); }, []) if (loading) { return <div>加载中...</div>; } return ( <div className="App"> <header className="App-header"> {data.length > 0 ? ( <Welcome text={"This data is from a JSON feed: " + data[1].title} /> ) : ( <div>暂无数据</div> )} </header> </div> );
内容的提问来源于stack exchange,提问作者MeltingDog
相关产品推荐
相关产品推荐

