React Native调用Yelp API每次加载触发3次请求,如何排查Hook问题?
问题原因
- 调用API时机错误:你当前挂载即调用
searchAPI的逻辑,和异步获取位置的逻辑是并行执行的,首次调用searchAPI时location还是初始空对象,此时访问location.coords会抛出异常,产生第一次无效请求。 - React 18+ 严格模式重复执行:开发环境下React默认开启的严格模式,会执行两次空依赖
useEffect的回调,产生后面两次请求,刚好凑成你遇到的3次请求现象。 - 依赖项缺失:调用
searchAPI的useEffect没有把用到的location、searchAPI加入依赖数组,不符合React Hook的依赖规则,会导致后续位置更新后无法重新发起请求。 - 潜在报错:代码中直接打印
location.coords.latitude,初始location为空对象时会直接抛出未定义错误。
修复方案
1. 调整自定义Hook逻辑
修改后的完整自定义Hook代码如下:
import React, { useEffect, useState, useCallback } from 'react'; import yelp from '../api/yelp'; import * as Location from 'expo-location'; export default () => { const [results, setResults] = useState([]); const [errorMessage, setErrorMessage] = useState(''); // 初始值改为null方便判断 const [location, setLocation] = useState(null); const [errorMsg, setErrorMsg] = useState(null); // 用useCallback包裹searchAPI,避免重渲染时重复创建 const searchAPI = useCallback(async (defaultTerm) => { // 调用前先判断location是否存在,避免参数错误 if (!location?.coords) return; try { const response = await yelp.get('/search', { params: { limit: 50, term: defaultTerm, latitude: location.coords.latitude, longitude: location.coords.longitude, radius: 4000, }, }); setResults(response.data.businesses); } catch (error) { setErrorMessage('Something went wrong 😢'); } }, [location]); // 只有location变化时才重新创建searchAPI useEffect(() => { (async () => { let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { setErrorMsg('Permission to access location was denied'); return; } let location = await Location.getCurrentPositionAsync({}); setLocation(location); })(); }, []); // 位置获取成功后再调用默认搜索,依赖项加入searchAPI useEffect(() => { // 只有location存在时才调用 if (location) { searchAPI(''); } }, [location, searchAPI]); // 打印加可选链,避免报错 console.log(`latitude: ${location?.coords?.latitude}`); console.log(`longitude: ${location?.coords?.longitude}`); return [searchAPI, results, errorMessage]; };
2. 开发环境重复请求说明
如果修改后开发环境还是出现两次请求,是React严格模式的正常表现,生产环境打包后会自动消失,不需要额外处理。如果要在开发环境关闭,找到项目入口文件移除<StrictMode>标签即可。
内容的提问来源于stack exchange,提问作者Scotch
相关产品推荐
相关产品推荐

