React中遍历数组调用计算函数更新useState?修正NaN数组问题
问题解决:计算距离返回NaN数组的修复
问题背景
我有一组包含经纬度的数据:
data=[{id: 4, lat: -33.85664180722481, long: 151.2153396118792},{..},{...}..];
我用calculateDistance()函数计算地图点击位置(location)与每个数据元素的距离,想把结果存入数组后用useState更新状态,但当前代码返回的是NaN数组。
当前代码
useEffect逻辑
useEffect(() => { const distance = data.map((hero) => { calculateDistance(location?.lat, location?.lng, hero?.lat,hero?.long); return distance; }); setDistance(distance); },[location, data]);
计算距离函数
const [distance, setDistance] = useState(null); const data = useHeroesData(); //console.log(data); const calculateDistance = (lat1, lon1, lat2, lon2) => { // 通用地理测量函数 var R = 6378.137; // 地球半径(公里) var dLat = (lat2 * Math.PI) / 180 - (lat1 * Math.PI) / 180; var dLon = (lon2 * Math.PI) / 180 - (lon1 * Math.PI) / 180; var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; return d; // 返回公里数 };
问题原因
- map回调返回错误:在
data.map的回调里,调用calculateDistance后没有返回计算结果,反而返回了正在定义的distance变量——此时distance还未完成赋值,导致每次迭代都返回undefined,最终数组全是undefined,后续计算自然得到NaN。 - 缺少边界检查:如果
location或hero的经纬度不存在(比如location未初始化、data元素缺失坐标),传入undefined到计算函数会触发无效数学运算,返回NaN。
修复方案
修正后的useEffect代码
useEffect(() => { // 先校验location是否有有效经纬度,避免无效计算 if (!location?.lat || !location?.lng) { setDistance([]); return; } const distanceArr = data.map((hero) => { // 校验当前hero的经纬度是否有效 if (!hero?.lat || !hero?.long) { return null; // 可根据需求返回0、'无效坐标'等替代值 } // 返回calculateDistance的计算结果 return calculateDistance(location.lat, location.lng, hero.lat, hero.long); }); setDistance(distanceArr); }, [location, data]);
额外优化:给计算函数加参数校验
在calculateDistance里提前校验参数有效性,进一步提升代码健壮性:
const calculateDistance = (lat1, lon1, lat2, lon2) => { // 校验参数是否为有效数字 if (typeof lat1 !== 'number' || typeof lon1 !== 'number' || typeof lat2 !== 'number' || typeof lon2 !== 'number') { return null; // 或0、NaN,根据业务需求调整 } var R = 6378.137; // 地球半径(公里) var dLat = (lat2 * Math.PI) / 180 - (lat1 * Math.PI) / 180; var dLon = (lon2 * Math.PI) / 180 - (lon1 * Math.PI) / 180; var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos((lat1 * Math.PI) / 180) * Math.cos((lat2 * Math.PI) / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var d = R * c; return d; // 返回公里数 };
说明
- 修正map的返回逻辑,确保每个迭代返回实际计算的距离值;
- 增加多层边界检查,避免传入无效坐标参数;
- 可选的函数参数校验,让代码在异常场景下更可控。
内容的提问来源于stack exchange,提问作者Vedat
相关产品推荐
相关产品推荐

