为何使用多个useFocusEffect会导致屏幕组件渲染两次?
问题原因分析
你的组件在屏幕获得焦点时渲染两次,核心原因如下:
- 两个
useFocusEffect各自触发了异步API请求,每个请求完成后都调用setMyState2更新同一个状态。React中每次调用setState都会触发组件重新渲染,两次状态更新就导致了两次额外的渲染。 - 你两个请求的是完全相同的接口,却重复发起请求并更新同一个state,这属于冗余操作,进一步加剧了重复渲染的问题。
解决方案
1. 合并请求与Effect(推荐)
既然两个请求的接口完全一致,直接合并成一个useFocusEffect,只发起一次请求,避免冗余操作和重复渲染:
import { useFocusEffect } from '@react-navigation/native'; import axios from 'axios'; import React, { useState } from 'react' import { View } from 'react-native' let renderCount = 0; function TestScreen() { const [myState2, setMyState2] = useState<any>(); renderCount++; console.log("component render number: ", renderCount); useFocusEffect( React.useCallback(async () => { const { data } = await axios.get<any>('https://dummyjson.com/quotes?limit=30'); setMyState2(data); }, []) ); return ( <View></View> ) } export default TestScreen
2. 若需独立请求,更新不同状态
如果确实需要两个独立的API请求(假设后续会修改为不同接口),请确保它们更新不同的state,避免重复修改同一个状态导致的多次渲染:
// 修改fetch函数,分别更新不同state const fetchAPIData1 = async () => { const { data } = await axios.get<any>('https://dummyjson.com/quotes?limit=30'); setMyState1(data); // 更新myState1 } const fetchAPIData2 = async () => { const { data } = await axios.get<any>('https://dummyjson.com/quotes?limit=30'); setMyState2(data); // 更新myState2 }
3. 避免重复请求(可选)
如果不需要每次屏幕获得焦点都重新请求数据,可以用useRef标记是否已完成首次请求:
const isDataLoaded = useRef(false); useFocusEffect( React.useCallback(async () => { if (!isDataLoaded.current) { const { data } = await axios.get<any>('https://dummyjson.com/quotes?limit=30'); setMyState2(data); isDataLoaded.current = true; } }, []) );
内容的提问来源于stack exchange,提问作者TheCulprit
相关产品推荐
相关产品推荐

