React中点击FlatList跳转至其他组件时遇navigate未定义问题
问题说明
在类组件Restaurants中使用FlatList展示内容,点击列表项时想跳转到FoodItems组件并传递字符串参数,却触发错误:Cannot read properties of undefined (reading 'navigate')。已安装react-navigation相关包,但对this.props的来源不清晰,代码复制自外部帖子,还自行编写了withRouter文件。
错误核心原因
- 路由库混淆:混用了Web端路由库
react-router-dom和React Native专用路由库react-navigation,两者API完全不兼容,自行编写的withRouter传递的是Web路由的navigation对象,并非React Native所需的导航实例。 - 类组件导航注入错误:类组件需要通过React Navigation提供的高阶组件注入
navigationprops,而非自定义的withRouter。 - 代码细节问题:
render方法中直接调用setState会触发无限重渲染;未初始化组件state;使用了React Native不支持的div标签;FlatList缺少必需的keyExtractor属性。
修复方案及完整代码
1. 安装必要依赖
如果使用React Navigation v5+,需补充安装兼容类组件的包:
npm install @react-navigation/compat @react-navigation/native-stack
2. 修正Restaurants组件代码
删除自定义的withRouter.js,改用React Navigation官方的withNavigation高阶组件:
import React, { Component } from 'react'; import { View, FlatList, Text, TouchableOpacity } from 'react-native'; import { withNavigation } from '@react-navigation/compat'; class Restaurants extends Component { constructor(props) { super(props); // 初始化组件state this.state = { restaurantsSet: false, restaurants: [] }; // 绑定方法避免this指向异常 this.settingRestaurants = this.settingRestaurants.bind(this); this.FlatListItemSeparator = this.FlatListItemSeparator.bind(this); this.FlatListHeader = this.FlatListHeader.bind(this); } componentDidMount() { // 将数据初始化逻辑移到生命周期方法,避免render中调用setState if (!this.state.restaurantsSet) { this.setState({ restaurantsSet: true }); // React Navigation v5+中参数通过route.params获取 this.settingRestaurants(this.props.route.params?.station); } } settingRestaurants(station) { // 这里替换为你的餐厅数据获取逻辑(比如API请求) this.setState({ restaurants: [ { id: 1, name: '餐厅A' }, { id: 2, name: '餐厅B' } ] }); } FlatListItemSeparator() { return <View style={{ height: 1, backgroundColor: '#ccc' }} />; } FlatListHeader() { return ( <View style={{ padding: 10, backgroundColor: '#f5f5f5' }}> <Text style={{ fontSize: 16, fontWeight: 'bold' }}>餐厅列表</Text> </View> ); } render() { return ( <View style={{ flex: 1 }}> {/* 替换React Native不支持的div为View */} <View style={{ height: 50, backgroundColor: '#2196F3' }}></View> <FlatList ItemSeparatorComponent={this.FlatListItemSeparator} ListHeaderComponent={this.FlatListHeader} style={{ flex: 1 }} data={this.state.restaurants} // FlatList必须添加keyExtractor keyExtractor={(item) => item.id.toString()} renderItem={({ item }) => ( <TouchableOpacity onPress={() => { // 通过注入的navigation对象跳转并传参 this.props.navigation.navigate('FoodItems', { message: 'my_message' }); }} style={{ padding: 15 }} > {/* 替换为你自己的Row组件,此处用Text示例 */} <Text>{item.name}</Text> </TouchableOpacity> )} /> </View> ); } } // 用withNavigation高阶组件注入navigation props export default withNavigation(Restaurants);
3. 配置全局路由容器(示例App.js)
确保Restaurants和FoodItems都在React Navigation的栈路由中注册:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import Restaurants from './Restaurants'; import FoodItems from './FoodItems'; const Stack = createNativeStackNavigator(); function App() { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Restaurants"> <Stack.Screen name="Restaurants" component={Restaurants} /> <Stack.Screen name="FoodItems" component={FoodItems} /> </Stack.Navigator> </NavigationContainer> ); } export default App;
4. FoodItems组件接收参数示例
import React from 'react'; import { View, Text } from 'react-native'; function FoodItems({ route }) { // 从route.params中获取传递的参数 const { message } = route.params; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>收到的消息:{message}</Text> </View> ); } export default FoodItems;
关键修复点总结
- 彻底移除
react-router-dom相关依赖和代码,统一使用React Navigation API - 类组件通过
withNavigation高阶组件获取navigation实例 - 避免在
render方法中调用setState,将数据初始化逻辑移到componentDidMount - 修复React Native不兼容的HTML标签,补充FlatList必需属性
内容的提问来源于stack exchange,提问作者Anish Mittal
相关产品推荐
相关产品推荐

