React Native抽屉导航仅生效一次,点击抽屉元素后应用冻结求助
问题描述
使用Drawer Navigation时,可从屏幕左侧滑动打开抽屉,但点击抽屉内元素后,整个应用冻结:滚动功能失效,抽屉无法再次打开,仅消息图标上的onPress方法仍能正常工作。
相关代码
App.js
const App = () => { return ( <NavigationContainer> <MainNavigation /> </NavigationContainer> ); };
Navigation代码
const Stack = createStackNavigator(); const Drawer = createDrawerNavigator(); const MainMenuNavigation = () => { return ( <Drawer.Navigator screenOptions={{"header": () => null}}> <Drawer.Screen name={Routes.Home} component={Home} /> <Drawer.Screen name={Routes.Profile} component={Profile} /> </Drawer.Navigator> ); }; const mainNavigation = () => { return ( <Stack.Navigator initialRouteName={Routes.Home} screenOptions={{"header": () => null, "headerShown": false}}> <Stack.Screen name={'Drawer'} component={MainMenuNavigation} /> </Stack.Navigator> ); };
Home页面代码
import React, {useState} from 'react'; import { SafeAreaView, Text, View, Pressable, FlatList, StatusBar, } from 'react-native'; import Title from '../../components/title/Title'; import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'; import {faEnvelope} from '@fortawesome/free-regular-svg-icons'; import style from './style'; import globalStyle from '../../Zassets/styles/main'; import UserStory from '../../components/UserStory/UserStory'; import UserPost from '../../components/userPosts/userPost'; import { Routes } from '../../navigation/routes'; const Home = ({navigation}) => { const data = [ {firstName: 'joseph', id: 1}, {firstName: 'Angel', id: 2}, {firstName: 'White', id: 3}, {firstName: 'Olivier', id: 4}, {firstName: 'john', id: 5}, {firstName: 'nick', id: 6}, {firstName: 'black', id: 7}, {firstName: 'Ann', id: 8}, {firstName: 'Mary', id: 9}, ]; const pageSize = 4; const [pageNumber, setPageNumer] = useState(1); const [loading, setLoading] = useState(false); const [renderedData, setRenderedData] = useState(data.slice(0, pageSize)); const posts = [ { firstName: 'Allison', lastName: 'becker', location: 'Sukabumi, Jawa Barat', likes: 1200, comments: 24, bookmarks: 55, id: 1, }, { firstName: 'Jennifer', lastName: 'Wilkson', location: 'Pondok leugnsir, Jawa Barat', likes: 1527, comments: 15, bookmarks: 25, id: 2, }, { firstName: 'Adam', lastName: 'spera', location: 'Boston, Massachusetts', likes: 125, comments: 6, bookmarks: 18, id: 3, }, { firstName: 'john', lastName: 'doe', location: 'NY, US', likes: 1525, comments: 63, bookmarks: 73, id: 4, }, { firstName: 'mary', lastName: 'Ann', location: 'Paris, France', likes: 244, comments: 23, bookmarks: 13, id: 5, }, ]; const postsPageSize = 2; const [pageNumberPosts, setpageNumberPosts] = useState(1); const [loadingPosts, setloadingPosts] = useState(false); const [renderedDataPosts, setrenderedDataPosts] = useState( posts.slice(0, postsPageSize), ); const pagination = (data, pageNumber, pageSize, posts = false) => { let startIndex = (pageNumber - 1) * pageSize; if (startIndex > data.length) { return []; } if (!posts) { setPageNumer(pageNumber); } else { setpageNumberPosts(pageNumber); } return data.slice(startIndex, startIndex + pageSize); }; return ( <SafeAreaView style={globalStyle.backgroundWhite}> <StatusBar backgroundColor={'#fff'} barStyle={'dark-content'} /> <FlatList ListHeaderComponent={ <> <View style={style.header}> <Title title={"Let's Explore"} /> <Pressable onPress={() => { navigation.navigate(Routes.Profile); }} style={style.messageIcon}> <FontAwesomeIcon icon={faEnvelope} color={'#CACDDE'} size={20} /> <View style={style.messageIconView}> <Text style={style.messageIconText}>2</Text> </View> </Pressable> </View> <View style={style.userStoryContainer}> <FlatList onMomentumScrollBegin={() => setLoading(false)} onEndReachedThreshold={0.5} keyExtractor={item => item.id.toString()} onEndReached={() => { if (!loading) { setLoading(true); setRenderedData(prev => [ ...prev, ...pagination(data, pageNumber + 1, pageSize), ]); setLoading(false); } }} showsHorizontalScrollIndicator={false} horizontal={true} data={renderedData} renderItem={({item}) => ( <UserStory firstName={item.firstName} /> )} /> </View> </> } onMomentumScrollBegin={() => setloadingPosts(false)} onEndReachedThreshold={0.5} keyExtractor={item => item.id.toString() + ' post'} onEndReached={() => { if (!loadingPosts) { setloadingPosts(true); setrenderedDataPosts(prev => [ ...prev, ...pagination(posts, pageNumberPosts + 1, postsPageSize, true), ]); setloadingPosts(false); } }} showsVerticalScrollIndicator={false} data={renderedDataPosts} renderItem={({item}) => ( <View style={style.userPostContainer}> <UserPost firstName={item.firstName} lastName={item.lastName} comments={item.comments} likes={item.likes} bookmarks={item.bookmarks} location={item.location} /> </View> )} /> </SafeAreaView> ); }; export default Home;
解决方案
1. 修正导航结构的错误配置
当前Stack导航的initialRouteName设置为Routes.Home,但Stack中仅包含名为Drawer的screen,这会导致导航状态混乱。同时,不必要的Stack嵌套会增加导航复杂度,建议直接使用Drawer作为主导航:
// 修改后的Navigation代码 const Drawer = createDrawerNavigator(); const MainNavigation = () => { return ( <Drawer.Navigator screenOptions={{header: () => null}}> <Drawer.Screen name={Routes.Home} component={Home} /> <Drawer.Screen name={Routes.Profile} component={Profile} /> </Drawer.Navigator> ); };
如果必须保留Stack嵌套,需修正initialRouteName为Stack中存在的screen名称:
const Stack = createStackNavigator(); const Drawer = createDrawerNavigator(); const MainMenuNavigation = () => { return ( <Drawer.Navigator screenOptions={{header: () => null}}> <Drawer.Screen name={Routes.Home} component={Home} /> <Drawer.Screen name={Routes.Profile} component={Profile} /> </Drawer.Navigator> ); }; const MainNavigation = () => { return ( <Stack.Navigator initialRouteName={'Drawer'} // 改为Stack中存在的screen名称 screenOptions={{header: () => null, headerShown: false}}> <Stack.Screen name={'Drawer'} component={MainMenuNavigation} /> </Stack.Navigator> ); };
2. 修复FlatList分页逻辑的状态更新问题
原pagination函数中直接修改页码状态,且onEndReached回调同步执行状态更新,会导致频繁的状态变更引发UI阻塞。调整逻辑,让分页函数仅负责数据切片,状态更新在回调中处理:
// 重写pagination函数,仅返回分页数据 const pagination = (data, pageNumber, pageSize) => { const startIndex = (pageNumber - 1) * pageSize; if (startIndex >= data.length) { return []; } return data.slice(startIndex, startIndex + pageSize); }; // 修改故事FlatList的onEndReached回调 onEndReached={() => { if (!loading) { setLoading(true); const nextPage = pageNumber + 1; const newData = pagination(data, nextPage, pageSize); if (newData.length > 0) { setRenderedData(prev => [...prev, ...newData]); setPageNumer(nextPage); } setLoading(false); } }} // 修改帖子FlatList的onEndReached回调 onEndReached={() => { if (!loadingPosts) { setloadingPosts(true); const nextPage = pageNumberPosts + 1; const newData = pagination(posts, nextPage, postsPageSize); if (newData.length > 0) { setrenderedDataPosts(prev => [...prev, ...newData]); setpageNumberPosts(nextPage); } setloadingPosts(false); } }}
3. 检查Profile页面的组件实现
应用冻结可能也与Profile页面的代码有关,需确保:
- 没有无限循环的状态更新
- 未在渲染阶段执行耗时操作
- 正确使用滚动组件(如
FlatList或ScrollView),避免布局溢出导致UI阻塞
4. 确保导航库版本兼容
更新@react-navigation相关依赖到最新稳定版,避免版本不兼容导致的异常:
npm install @react-navigation/native@latest @react-navigation/drawer@latest react-native-gesture-handler@latest react-native-reanimated@latest
内容的提问来源于stack exchange,提问作者legates
相关产品推荐
相关产品推荐

