React Navigation V6中useFocusEffect内使用useCallback触发无效Hook调用错误求助
问题回顾
你按照React Navigation V6的useFocusEffect文档示例尝试在其内部使用useCallback,却触发了以下错误:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- React和React DOM版本不匹配
- 违反了Hooks使用规则
- 应用中存在多个React副本
你的代码中useFocusEffect的写法是这样的:
useFocusEffect(() => { React.useCallback(() => { console.log(latVal, longVal); fetchWeatherData(); fetchForecastData(); }, [latVal]); });
错误原因分析
问题的核心是违反了React Hooks的调用规则:所有React Hooks(包括useCallback)必须直接在函数组件的顶层作用域调用,不能嵌套在普通函数、另一个Hook的回调函数内部。
你现在的写法是把useCallback放在了useFocusEffect的回调函数里,这相当于在一个普通函数内部调用Hook,完全不符合规则,所以React抛出了错误。
官方文档的示例是把useCallback作为useFocusEffect的直接参数,而不是嵌套在回调里面,你可能误解了示例的写法。
修复方案
我们需要调整代码结构,让所有Hooks都在组件顶层调用,同时保持useFocusEffect的正确用法:
步骤1:用useCallback包裹数据请求函数(可选但推荐)
为了避免组件每次渲染都创建新的请求函数,我们先把fetchWeatherData和fetchForecastData用useCallback包裹,并明确它们的依赖项:
const fetchWeatherData = React.useCallback(async () => { const requestOptions = { method: 'GET', headers: {'Content-Type': 'application/json'}, }; try { const response = await fetch( `https://api.openweathermap.org/data/2.5/weather?lat=${latVal}&lon=${longVal}&appid=${API_KEY}`, requestOptions, ); const responseData = await response.json(); console.log(responseData); setData(responseData); } catch (err) { console.log(err); } }, [latVal, longVal, API_KEY]); // 依赖所有用到的外部变量 const fetchForecastData = React.useCallback(async () => { const requestOptions = { method: 'GET', headers: {'Content-Type': 'application/json'}, }; try { const response = await fetch( `https://api.openweathermap.org/data/2.5/forecast?lat=${latVal}&lon=${longVal}&appid=${API_KEY}`, requestOptions, ); const responseData = await response.json(); setForecastData(responseData.list); } catch (err) { console.log(err); } }, [latVal, longVal, API_KEY]);
步骤2:修正useFocusEffect的写法
把useCallback直接作为useFocusEffect的参数,确保它在组件顶层作用域被调用:
useFocusEffect( React.useCallback(() => { console.log(latVal, longVal); fetchWeatherData(); fetchForecastData(); }, [latVal, longVal, fetchWeatherData, fetchForecastData]) // 依赖请求函数和相关变量 );
额外优化说明
- 移除了原代码中
await和.then()混合使用的写法,改用纯async/await,代码更清晰易读。 - 确保所有依赖项都被添加到
useCallback的依赖数组中,避免因依赖缺失导致的 stale closure(闭包过时)问题。
排除其他可能问题
从你的package.json来看:
- React 18.1.0和React Native 0.70.1版本匹配,不存在版本不匹配问题。
- 依赖中没有重复安装React的迹象,排除多个React副本的问题。
所以修复上述Hook调用位置的问题后,错误应该就能解决了。
内容的提问来源于stack exchange,提问作者Fashad Ahmed

