useEffect中Axios请求引发无限渲染问题排查
解决React Native中useEffect无限重复执行请求的问题
问题根源
你的代码中useEffect本应只执行一次GET请求,但调用setProfile更新上下文状态后,请求却无限重复,核心原因有两点:
useEffect依赖数组不完整:请求中用到了user对象,但未将其加入依赖数组,若user的引用在组件渲染时发生变化,会导致useEffect意外重复触发。- 不必要的状态更新引发循环渲染:每次调用
setProfile时都创建新数组wholeArray,导致profile的引用始终变化,触发组件重新渲染;同时内部定义的ProfileViewComponent每次渲染都会重新创建,加剧了渲染循环。
具体修复步骤
1. 完善useEffect依赖并添加请求锁
给useEffect补充正确依赖,同时通过状态标记请求完成状态,避免重复触发:
const { profile, setProfile } = useContext(ProfileContext); const [hasChange, setHasChange] = useState(null); const [photo, setPhoto] = useState(null); const [isLoaded, setIsLoaded] = useState(false); // 添加请求完成标记 useEffect(() => { if (!isLoaded) { (async () => { try { const { data } = await axios.get( `https://qr-queue.com/api/customer/get/${user.customer_id}`, { headers: { Authorization: user.token, 'Content-Type': 'application/json', }, } ); getProfile(data); setIsLoaded(true); // 请求完成后标记为已加载 } catch (e) { console.log(e); setIsLoaded(true); // 失败也标记,避免重复请求 } })(); } }, [user, isLoaded]); // 添加user和isLoaded到依赖数组
2. 优化setProfile更新逻辑
仅当数据实际变化时才更新上下文状态,避免不必要的渲染:
function getProfile(result) { try { console.log(result.data.image); setPhoto(result.data.image); const newProfile = [result.data]; // 对比新旧数据,仅当不同时更新 if (JSON.stringify(newProfile) !== JSON.stringify(profile)) { setProfile(newProfile); } } catch (e) { console.log(e); } }
3. 避免组件内部重复创建元素
用useMemo包裹ProfileViewComponent,仅当profile变化时重新创建:
// 保持renderContent不变,可移到组件外部进一步优化 function renderContent(itemData, onPressHandler) { // 原代码逻辑 } // 在组件内部用useMemo包裹 const ProfileViewComponent = useMemo(() => ( <FlatList data={profile} keyExtractor={(item) => item.ID} renderItem={renderContent} /> ), [profile]); // 仅依赖profile
额外提示
- 如果
user是来自上下文或props的对象,建议直接依赖user.customer_id和user.token而非整个user对象,或用useMemo确保user引用稳定。 - 开发环境下React严格模式会让
useEffect执行两次,属于正常校验逻辑,生产环境会恢复单次执行。
内容的提问来源于stack exchange,提问作者Dockies
相关产品推荐
相关产品推荐

