React中使用useEffect钩子发起API数据请求的写法是否正确?
问题原因分析
- 初始值类型不匹配:你给
data设置的初始值是数组[],但实际使用时是将data作为对象读取keyname属性,初始渲染阶段data.keyname为undefined,对undefined执行map方法会直接触发报错。 - 请求URL拼写错误:fetch的目标地址写的是
htts://localhost/api/,少了一个字母t,正确应为https://localhost/api/,这个错误会导致请求失败直接进入catch逻辑,不会触发setData更新状态。 - 错误处理逻辑不完善:当前只有请求成功时才会修改
loading为false,请求失败时loading会一直保持为true,影响状态判断。 - 缺少渲染前置校验:没有对
data.keyname的存在性、类型做校验就直接调用map,即使请求成功,如果接口返回结构不符合预期也会报错。
修复方案
- 修正状态初始值:如果你确认接口返回的是包含
keyname字段的对象,调整data的初始值结构和你预期的接口返回结构对齐
// 初始值直接和接口返回结构对齐,避免初始渲染报错 const [ data, setData ] = useState({ keyname: [] }); const [ loading, setLoading ] = useState(false);
- 修正fetch请求的URL拼写,同时在catch逻辑里补充loading重置规则
useEffect(() => { const loadData = async () => { try { setLoading(true); // 修正拼写错误 const response = await fetch(`https://localhost/api/`); const json = await response.json(); setData(json); } catch (error) { console.log("error: " + error); } finally { // 无论请求成功失败都重置loading状态 setLoading(false); } } loadData(); }, []);
- 渲染时增加状态判断,避免对不存在的属性执行方法
// 方案1:结合loading状态控制渲染 { loading ? <option>加载中...</option> : data.keyname.map((item, index) => { return ( <option key={index} value={item.displayName}> {item.displayName} </option> ); }) } // 方案2:用可选链做兼容兜底,不需要额外判断loading也可以避免报错 { data?.keyname?.map((item, index) => { return ( <option key={index} value={item.displayName}> {item.displayName} </option> ); }) ?? [] }
额外优化建议:如果列表项有唯一id属性,尽量用id代替index作为元素的key值,避免列表重排时出现渲染异常。
内容的提问来源于stack exchange,提问作者zeropsi
相关产品推荐
相关产品推荐

