React Native点击食品分类按钮无法跳转至列表页问题求助
Hey there! Let's work through why your navigation isn't working and fix those data fetching issues too. I've gone through your code and spotted several key problems that are causing the trouble:
First, let's fix the navigation and logic issues in Categories.js
- You were trying to access route params the wrong way with
this.props.navigation.navigate('state')— that's not how you retrieve params passed via navigation. To get params from the navigation state, you needthis.props.navigation.state.params(this matches the older React Navigation syntax your code uses). - Your
onPresshandler was attached to the<Text>component, which works but limits the touch target. It's better to attach it directly to the<TouchableOpacity>so users can tap anywhere on the button area. Also, make sure you're navigating to the correct screen name (I'm assuming it's 'Details' since that's your second page component). - The
FoodCatmethod andcomponentDidCatchusage were misplaced:componentDidCatchis for catching rendering errors, not fetching data. The food data fetch should happen in theDetailscomponent, notCategories. - You forgot to import
Dimensionseven though you're using it to get the window size. - Remove
AppRegistry.registerComponent— React Navigation handles registering your screens when you set up the navigator, so this line is unnecessary here.
Here's the corrected Categories.js:
import React, { Component } from 'react'; import { Text, TouchableHighlight, View, StyleSheet, Platform, FlatList, TouchableOpacity, Dimensions } from 'react-native'; // Added missing Dimensions import var screen = Dimensions.get('window'); export default class Categories extends Component { static navigationOptions = { title: 'Product2' }; state = { data: [], }; fetchData = async () => { const response_Cat = await fetch('http://192.168.254.102:3307/Categories/'); const category_Cat = await response_Cat.json(); this.setState({ data: category_Cat }); }; componentDidMount() { this.fetchData(); }; render() { const { navigate } = this.props.navigation; return ( <View style={styles.container}> <FlatList data={this.state.data} renderItem={({ item }) => ( <TouchableOpacity style={styles.buttonContainer} onPress={() => navigate('Details', { id: item.id })} // Attached onPress to TouchableOpacity, navigating to Details screen > <Text style={styles.buttonText}>{item.cat_name}</Text> </TouchableOpacity> )} keyExtractor={(x, i) => i.toString()} // Ensured key is a string (best practice) /> </View> ); } } // Add your custom styles here const styles = StyleSheet.create({ container: { flex: 1, padding: 10, backgroundColor: '#fff', }, buttonContainer: { padding: 15, marginVertical: 5, backgroundColor: '#f0f0f0', borderRadius: 8, }, buttonText: { fontSize: 16, textAlign: 'center', }, });
Next, let's fix the Details.js component
- Same param-access mistake here: use
this.props.navigation.state.paramsto get the category ID passed fromCategories. - Your fetch URL wasn't using the category ID, so it was fetching all foods instead of the selected category's items. We'll add the ID to the URL here.
- You were setting
dataSourcetoresponseJson.data, but if your backend returns the array of foods directly (not wrapped in adataobject), you should useresponseJsoninstead. Adjust this if your API structure is different. - Again, remove
AppRegistry.registerComponentas it's not needed with React Navigation.
Here's the corrected Details.js:
import React, { Component } from 'react'; import { StyleSheet, FlatList, Text, View } from 'react-native'; export default class Details extends Component { constructor() { super(); this.state = { dataSource: [] }; } renderItem = ({ item }) => { return ( <View style={{ flex: 1, flexDirection: 'row', padding: 12, borderBottomWidth: 1, borderBottomColor: '#eee' }}> <View style={{ flex: 1, justifyContent: 'center' }}> <Text style={{ fontSize: 16, fontWeight: '500' }}>{item.menu_desc}</Text> <Text style={{ fontSize: 14, color: '#666', marginTop: 4 }}>${item.menu_price}</Text> </View> </View> ); }; componentDidMount() { // Get the category ID from navigation params (added optional chaining to avoid errors if no param exists) const categoryId = this.props.navigation.state.params?.id; if (!categoryId) { console.log('No category ID was passed to Details screen'); return; } const url = `http://192.168.254.102:3307/foods/${categoryId}`; // Added category ID to fetch URL fetch(url) .then((response) => response.json()) .then((responseJson) => { console.log('Fetched foods:', responseJson); // If your API returns data inside a 'data' property, change this to responseJson.data this.setState({ dataSource: responseJson }); }) .catch((error) => { console.error('Error fetching foods:', error); }); } render() { console.log('Current data source:', this.state.dataSource); return ( <View style={styles.container}> <FlatList data={this.state.dataSource} renderItem={this.renderItem} keyExtractor={(item, index) => index.toString()} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 10, backgroundColor: '#fff', }, });
One last thing: Make sure your navigator is set up correctly!
You need to register both screens in your navigation stack (I'm using React Navigation v4 here, which matches your code's syntax):
import { createStackNavigator, createAppContainer } from 'react-navigation'; import Categories from './categories'; import Details from './Details'; const AppNavigator = createStackNavigator({ Categories: { screen: Categories, navigationOptions: { title: 'Food Categories', // Optional: customize the title } }, Details: { screen: Details, navigationOptions: ({ navigation }) => ({ title: `Category Foods`, // Optional: dynamic title based on category }) }, }); export default createAppContainer(AppNavigator);
With these fixes, your category buttons should navigate to the Details screen correctly, and the Details screen will fetch only the foods for the selected category.
内容的提问来源于stack exchange,提问作者Violet
相关产品推荐
相关产品推荐

