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

React Native项目出现Excessive number of pending callbacks错误求助

React Native 待处理回调数量过多(501)错误排查与解决

错误提示

请反馈:待处理回调数量过多:501。部分待处理回调可能因从未被Native代码调用而泄漏 请反馈:待处理回调数量过多:501。部分待处理回调可能因从未被Native代码调用而泄漏

相关代码

const SCREEN_WIDTH = Dimensions.get("window").width;

const ProductView = ({ navigation }) => {
    //const getDiv = useSelector((state) => state.reducerDiv.divId)

    const [itemsData, setItemsData] = useState([]);
    const [currentIndex, setCurrentIndex] = useState(0);
    const [loading, setLoading] = useState(true);
    const route = useRoute();
    const id = route.params?.id;
    const item = itemsData?.find((i) => i.id === id);

    useEffect(() => {
        getData();
    }, []);

    const getData = async () => {
        try {
        const response = await axios.post(`url`);
        setItemsData(response.data.data);
        } catch (error) {
        console.warn(error);
        } finally {
        setLoading(false);
        }
    };

    useEffect(() => {
        if (item) {
        setCurrentIndex(itemsData.indexOf(item));
        }
    }, [item, id]);

    const handleScroll = (event) => {
        const contentOffset = event.nativeEvent.contentOffset.x;
        const index = Math.round(contentOffset / SCREEN_WIDTH);
        setCurrentIndex(index);
    };
    // <-----------------------------------horizontal screen--------------------------------------------->
    const renderItem = ({ item }) => (
        <View style={styles.body} key={item.id}>
        <ScrollView>
            <View style={styles.container}>
            <View style={{ width: SCREEN_WIDTH, paddingEnd: 50 }}>
                <Image source={{ uri: item.image ? item.image : null }} style={styles.productImg} resizeMode="contain" />
            </View>
            <View style={{ paddingEnd: 50 }}>
                <View style={{ flex: 1, flexDirection: "row", marginTop: 15, justifyContent: "space-between" }}>
                <View style={{ flexDirection: "column" }}>
                    <Text style={styles.textItem}>Brand name</Text>
                    <Text style={styles.title}>{item?.title}</Text>
                </View>
                <View style={{ flex: 1, flexDirection: "row", justifyContent: "flex-end" }}>
                    <TouchableOpacity>
                    <Image source={require("../image/share.png")} style={styles.shareImg} />
                    </TouchableOpacity>

                    <TouchableOpacity>
                    <Image source={require("../image/screenshot.png")} style={styles.shareImg} />
                    </TouchableOpacity>
                </View>
                </View>
            </View>
            </View>
        </ScrollView>
        </View>
    );
    if (loading) {
        return <Text>Loading...</Text>;
    }

    return (
        <LinearGradient colors={["#7ABF49", "#13A15D"]} start={{ x: 0.99, y: 0 }} end={{ x: 1, y: 0 }} style={styles.linearGradient}>
        <HeaderItem navigation={navigation} />

        <FlatList
            data={itemsData}
            horizontal={true}
            pagingEnabled={true}
            showsHorizontalScrollIndicator={false}
            onScroll={handleScroll}
            scrollEventThrottle={160}
            contentOffset={{
            x: currentIndex * SCREEN_WIDTH,
            y: 0,
            }}
            keyExtractor={(item) => item.id.toString()}
            renderItem={renderItem}
        />
        </LinearGradient>
    );
};

问题根源

该错误是因为状态更新与FlatList滚动事件形成循环触发,导致Native层回调堆积:

  • currentIndex变化时,FlatList通过contentOffset强制滚动,触发onScroll事件,再次调用setCurrentIndex,反复触发Native回调
  • 第二个useEffect在item更新时也会设置currentIndex,进一步加剧循环

修复方案

1. 替换contentOffset为手动滚动

移除FlatList的contentOffset属性,改用scrollToIndex在currentIndex变化时手动控制滚动,避免循环触发:

const flatListRef = useRef(null);

// 新增useEffect处理滚动
useEffect(() => {
  if (flatListRef.current && itemsData.length > 0) {
    flatListRef.current.scrollToIndex({
      index: currentIndex,
      animated: false
    });
  }
}, [currentIndex, itemsData.length]);

// 修改FlatList,添加ref并移除contentOffset
<FlatList
  ref={flatListRef}
  data={itemsData}
  horizontal={true}
  pagingEnabled={true}
  showsHorizontalScrollIndicator={false}
  onScroll={handleScroll}
  scrollEventThrottle={160}
  keyExtractor={(item) => item.id.toString()}
  renderItem={renderItem}
/>

2. 优化handleScroll的状态更新逻辑

只有当计算出的索引与当前currentIndex不同时才更新状态,减少不必要的触发:

const handleScroll = (event) => {
  const contentOffset = event.nativeEvent.contentOffset.x;
  const index = Math.round(contentOffset / SCREEN_WIDTH);
  if (index !== currentIndex) { // 新增判断
    setCurrentIndex(index);
  }
};

3. 优化第二个useEffect的触发逻辑

添加索引判断,避免重复设置currentIndex,同时补充完整依赖项:

useEffect(() => {
  if (item) {
    const newIndex = itemsData.indexOf(item);
    if (newIndex !== currentIndex) { // 新增判断
      setCurrentIndex(newIndex);
    }
  }
}, [item, id, currentIndex, itemsData]); // 补充依赖项

4. 修复嵌套ScrollView的滚动冲突

给内部ScrollView添加nestedScrollEnabled属性,避免干扰FlatList的滚动事件:

<ScrollView nestedScrollEnabled={true}>
  // ...内部原有内容
</ScrollView>

内容的提问来源于stack exchange,提问作者Raja Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 12:50:41