React Navigation搭配FlatList使用时withNavigation渲染报错如何解决
问题说明
运行项目时触发如下渲染错误:
Render Error. withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context
错误译文:渲染错误,withNavigation仅可在导航器的视图层级中使用,被包裹的组件无法从props或上下文中获取navigation导航对象。
复现规则:
- 调用
navigation.navigate跳转至内置FlatList组件的PrEntery页面时必现该错误 - 若将PrEntery中的
FlatList替换为多个普通组件,导航功能可正常运行
相关复现代码
App.js
const MainStackScreen = () => { return ( <NavigationContainer> <MainStack.Navigator screenOptions={{headerShown: false}} > <MainStack.Screen name = "Home" component ={Home}/> <MainStack.Screen name = "PrEntery" component = {PrEntery}/> </MainStack.Navigator> </NavigationContainer> ); }; export default MainStackScreen;
Home.js
const Home = ({navigation}) => { return( <View style = {{height:'100%',width:'100%',backgroundColor:'#141212'}}> <SafeAreaView> <View style={{marginTop:200}}> <TouchableOpacity onPress={()=>{ navigation.navigate('PrEntery') }}> <HomeButton text = 'Enter PR'/> </TouchableOpacity> </View> <View style={{marginTop:40}}> <TouchableOpacity> <HomeButton text = 'Record Book'/> </TouchableOpacity> </View> </SafeAreaView> </View> ); }; export default Home;
PrEntery.js
const renderItem = ({index}) => { return( <EnterPr text = {index}/> ); }; const PrEntery = () => { return( <View style = {{height:'100%',width:'100%',backgroundColor:'#141212'}}> <SafeAreaView> <FlatList data={LIFTS} renderItem = {renderItem} /> </SafeAreaView> </View> ); }; export default PrEntery;
问题根因
报错核心原因是FlatList是虚拟滚动组件,列表项采用独立调度的懒渲染机制。当前代码把renderItem定义在PrEntery组件的外层作用域,列表项渲染时无法继承导航器注入的Context,因此被withNavigation包裹的EnterPr组件无法获取navigation对象。
替换为普通组件时,所有节点都处于页面的同步渲染树内,导航上下文可以正常传递,因此不会触发报错。
解决方案
任选以下一种方式修复即可:
- 将
renderItem移动到PrEntery组件内部定义,让列表项渲染时可以正确继承导航上下文,修复后代码:
// PrEntery.js const PrEntery = () => { // renderItem移到组件内部 const renderItem = ({index}) => { return( <EnterPr text = {index}/> ); }; return( <View style = {{height:'100%',width:'100%',backgroundColor:'#141212'}}> <SafeAreaView> <FlatList data={LIFTS} renderItem = {renderItem} keyExtractor={(item, index) => index.toString()} /> </SafeAreaView> </View> ); }; export default PrEntery;
- 移除
EnterPr组件外层的withNavigation包裹,直接在PrEntery页面获取navigation对象,通过props手动传递给列表项,彻底绕开虚拟列表的上下文穿透问题,修复后代码:
// PrEntery.js const PrEntery = ({navigation}) => { const renderItem = ({index}) => { // 手动透传navigation return( <EnterPr text = {index} navigation={navigation}/> ); }; return( <View style = {{height:'100%',width:'100%',backgroundColor:'#141212'}}> <SafeAreaView> <FlatList data={LIFTS} renderItem = {renderItem} keyExtractor={(item, index) => index.toString()} /> </SafeAreaView> </View> ); }; export default PrEntery;
*补充:建议给FlatList添加keyExtractor属性,避免列表渲染出现性能问题或警告。
内容的提问来源于stack exchange,提问作者Rcardona
相关产品推荐
相关产品推荐

