React Native滑动Material Top Tab Navigator时出现onAnimatedValueUpdate警告求助
使用React Native CLI和React Navigation 6.x开发移动端应用时,使用Material Top Tab Navigator左右滑动切换标签页,控制台持续抛出警告:WARN Sending 'onAnimatedValueUpdate' with no listeners registered。已尝试useFocusEffect、手动添加监听器等方法,问题仍未解决。
相关代码
HomeStack.tsx
import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs'; import React, {useEffect} from 'react'; import AScreen from '../screens/Home/AScreen'; import BScreen from '../screens/Home/BScreen'; const Tab = createMaterialTopTabNavigator(); const HomeStack = () => { useEffect(() => { console.log('HomeStack'); }, []); return ( <Tab.Navigator screenOptions={{ tabBarActiveTintColor: '#fff', tabBarStyle: { borderTopWidth: 0.2, borderTopColor: '#ccc', }, tabBarIndicatorStyle: { backgroundColor: '#fff', }, lazy: true, }} initialRouteName="A" shouldRasterizeIOS> <Tab.Screen name="A" component={AScreen} /> <Tab.Screen name="B" component={BScreen} /> </Tab.Navigator> ); }; export default HomeStack;
BScreen.tsx
const BScreen: React.FC = ({navigation}: any) => { const [refreshing, setRefreshing] = useState(false); useFocusEffect( useCallback(() => { const function = async () => { console.log('function useFocusEffect'); await function2({pageParam: 0}); }; function(); }, [navigation]), ); const function2 = async ({pageParam = 0}) => { const limit = 10; const offset = pageParam * limit; // ... DATA Handling if (error) { throw error; } if (data.length === 0) { return {data, nextPage: false}; } return {data, nextPage: pageParam + 1}; }; };
AScreen.tsx
import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {VirtualizedList, ActivityIndicator, Text, View} from 'react-native'; import {hook} from '../../hooks/hook'; import MyITEM from '...'; import {useIsFocused} from '@react-navigation/native'; const AScreen: React.FC = () => { useEffect(() => { console.log('AScreen Initalized'); }, []); const isFocused = useIsFocused(); useEffect(() => { console.log('AScreen isFocused: ', isFocused ? 'true' : 'false'); }, [isFocused]); const [refreshing, setRefreshing] = useState(false); // ...data fetching with react-query (infinite query) const renderFooter = useCallback(() => { if (isFetchingNextPage || hasNextPage) { return <ActivityIndicator />; } return null; }, [isFetchingNextPage, hasNextPage]); const renderItem = useCallback( ({item}: any) => ( <MyITEM /> ), [], ); const getItem = useCallback((data, index) => data[index], []); const getItemCount = useCallback(data => data.length, []); const onRefresh = useCallback(() => { setRefreshing(true); refetch(); setRefreshing(false); }, [refetch]); const posts = useMemo( () => data?.pages?.flatMap(page => page.data) || [], [data?.pages], ); if (status === 'loading') { return <ActivityIndicator />; } if (status === 'error') { return <Text>Error A</Text>; } return ( <View style={{flex: 1}}> <VirtualizedList data={posts} renderItem={renderItem} keyExtractor={(item, index) => index.toString()} ListFooterComponent={renderFooter} getItem={getItem} getItemCount={getItemCount} onRefresh={onRefresh} refreshing={refreshing} onEndReached={() => { if (hasNextPage && !isFetchingNextPage) { console.log('onEndReached'); fetchNextPage(); } }} onEndReachedThreshold={0.5} /> </View> ); }; export default AScreen;
解决方案
1. 升级React Navigation相关依赖
该警告多为@react-navigation/material-top-tabs或其底层依赖react-native-tab-view的已知版本问题,升级到最新稳定版即可修复:
# npm npm update @react-navigation/native @react-navigation/material-top-tabs react-native-tab-view # yarn yarn upgrade @react-navigation/native @react-navigation/material-top-tabs react-native-tab-view
2. 手动为动画值添加空监听器
通过Tab Navigator的引用,手动为其内部动画值添加空监听器,避免警告触发:
修改HomeStack代码:
import {createMaterialTopTabNavigator} from '@react-navigation/material-top-tabs'; import React, {useEffect, useRef} from 'react'; import AScreen from '../screens/Home/AScreen'; import BScreen from '../screens/Home/BScreen'; import {TabView} from 'react-native-tab-view'; const Tab = createMaterialTopTabNavigator(); const HomeStack = () => { const tabViewRef = useRef<TabView>(null); useEffect(() => { console.log('HomeStack'); // 添加空监听器消除警告 const navigationState = tabViewRef.current?.getState(); if (navigationState?.position) { const listenerId = navigationState.position.addListener('onAnimatedValueUpdate', () => {}); return () => { navigationState.position.removeListener(listenerId); }; } }, []); return ( <Tab.Navigator ref={tabViewRef} screenOptions={{ tabBarActiveTintColor: '#fff', tabBarStyle: { borderTopWidth: 0.2, borderTopColor: '#ccc', }, tabBarIndicatorStyle: { backgroundColor: '#fff', }, lazy: true, }} initialRouteName="A" shouldRasterizeIOS> <Tab.Screen name="A" component={AScreen} /> <Tab.Screen name="B" component={BScreen} /> </Tab.Navigator> ); }; export default HomeStack;
3. 修正VirtualizedList的刷新逻辑
AScreen中onRefresh的状态更新是同步执行的,可能引发动画异常,修改为异步等待:
const onRefresh = useCallback(async () => { setRefreshing(true); await refetch(); setRefreshing(false); }, [refetch]);
4. 临时禁用滑动动画(不推荐)
如果上述方法均无效,可临时禁用Tab的滑动或动画来规避警告,但会影响用户体验:
<Tab.Navigator screenOptions={{ // 其他配置... swipeEnabled: false, // 禁用滑动切换 // 或直接禁用动画 animationEnabled: false, }} >
内容的提问来源于stack exchange,提问作者Merovingian
相关产品推荐
相关产品推荐

