You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 05:48:01