React双Hook调用多级API时,如何正确放置if判断语句?
React链式API调用的Hook合规写法与条件判断位置
问题核心
你的代码存在几个关键问题:
- 条件判断
if (!data) return null放在了两个Hook之间,违反了React Hook「必须在组件顶层调用、不能在条件/循环/嵌套函数中调用」的规则,直接触发报错。 - 第二个
useEffect没有设置依赖项,会在组件每次渲染时重复执行,引发无限循环。 - 第一个API的
setData(data.id)逻辑大概率有误——从后续data.map的用法来看,你需要的是一组id数组,而非单个id,这里明显是对API返回结构的处理写错了。
正确的条件判断位置
条件判断必须放在所有Hook声明完成之后、组件返回JSX之前,这样既不违反Hook规则,又能在data未就绪时提前返回,避免后续逻辑因undefined报错。
修正后的完整代码
import React, { useEffect, useState } from 'react'; import { View, Text } from 'react-native'; // 修正原代码的解构错误 export default function MyComponent() { const [data, setData] = useState([]); // 初始值设为空数组,避免map时因undefined报错 const [loc, setLoc] = useState([]); // 第一个API:获取id列表 useEffect(() => { fetch('https://www.roads.com/road/api/auth/web/roadControl?projectId=765&pageSize=150') .then((response) => response.json()) .then((resData) => { // 根据实际API返回结构调整,比如resData.list或直接resData,确保是数组 setData(resData); }) .catch((error) => console.error(error)); }, []); // 第二个API:根据id列表获取详情 useEffect(() => { // 只有当data有内容时才执行请求 if (!data.length) return; async function fetchDetails() { try { const detailPromises = data.map((item) => fetch(`https://www.roads.com/road/web/roadControl/${item.id}`) // 假设data每一项包含id字段,按需调整 .then((response) => response.json()) .catch((error) => { console.error(error); return null; // 单个请求失败时返回null,不阻塞其他请求 }) ); const details = await Promise.all(detailPromises); setLoc(details.filter(Boolean)); // 过滤掉请求失败的null项 } catch (error) { console.log(error); } } fetchDetails(); }, [data]); // 依赖data,仅当id列表更新时执行 // 条件判断放在所有Hook之后 if (!data.length) { return <View><Text>加载中...</Text></View>; // 替换返回null,显示友好加载态 } // 渲染业务UI return ( <View> {/* 这里编写你的loc数据渲染逻辑 */} </View> ); }
关键调整说明
- Hook顺序合规:所有
useState和useEffect都放在组件顶层,条件判断在最后,完全符合React Hook规则。 - 避免无限循环:第二个
useEffect依赖data,仅当第一个API返回的id列表更新时才触发,不会重复执行。 - 初始值优化:将
data初始值设为空数组,避免data.map因undefined抛出错误。 - 容错处理:单个详情请求失败时返回
null,后续通过filter(Boolean)过滤无效数据,保证整体流程不中断。 - 体验优化:用加载提示替换返回
null,提升用户感知。
内容的提问来源于stack exchange,提问作者ASIF AKBER
相关产品推荐
相关产品推荐

