You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native项目报错:Cannot read property 'categoryId' of undefined 求助

问题排查:React Native跳转时Cannot read property 'categoryId' of undefined错误

开发Daily Fashion应用时,从HomeScreen跳转到ShowProductScreen时触发错误:Cannot read property 'categoryId' of undefined,错误定位到ShowProductScreen中的const category = route.params.categoryId代码行。尝试多种方案未解决,附上相关代码请求协助:


HomeScreen.js

import {
  View,
  Text,
  StyleSheet,
  Image,
  FlatList,
  TouchableOpacity,
} from 'react-native';
import React from 'react';
import {imageSlider} from '../../data/Data';
import {SliderBox} from 'react-native-image-slider-box';
import {categoryList} from '../../data/Data';
const HomeScreen = props => {
  const {navigation} = props;
  return (
    <View style={styles.mainContainer}>
      <SliderBox
        images={imageSlider}
        autoplay={true}
        circleLoop={true}
        sliderBoxHeight={250}
      />
      <View style={styles.titleContainer}>
        <Text style={styles.text}>Categories</Text>
      </View>
      <FlatList
        data={categoryList}
        key={3}
        numColumns={3}
        keyExtractor={item => item.id}
        contentContainerStyle={styles.flatListContainer}
        showsVerticalScrollIndicator={false}
        renderItem={({item}) => {
          return (
            <TouchableOpacity
              style={styles.button}
              onPress={() =>
                navigation.navigate('ShowProduct', {categoryId: item.id})
              }>
              <Image source={{uri: item.icon}} style={styles.icon} />
              <Text style={styles.itemName}>{item.name}</Text>
            </TouchableOpacity>
          );
        }}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  mainContainer: {
    backgroundColor: 'white',
    flex: 1,
  },
  titleContainer: {
    marginTop: 16,
    alignItems: 'center',
  },
  text: {
    fontSize: 18,
    fontWeight: 'bold',
    color: 'black',
  },
  flatListContainer: {
    padding: 8,
  },
  button: {
    flex: 1,
    margin: 8,
    borderWidth: 1,
    borderColor: '#7CAF58',
    borderRadius: 10,
    height: 130,
    justifyContent: 'center',
    alignItems: 'center',
  },
  icon: {
    width: 100,
    height: 100,
    resizeMode: 'contain',
  },
  itemName: {
    color: 'black',
  },
});
export default HomeScreen;

ShowProductScreen.js

import {
  StyleSheet,
  Text,
  View,
  FlatList,
  Image,
  TextInput,
  TouchableOpacity,
} from 'react-native';
import {Icon} from 'react-native-elements';
import React, {useEffect, useState} from 'react';
import realm from '../../store/realm';
const ShowProductScreen = props => {
  const {route} = props;
  const category = route.params.categoryId;
  const [data, setData] = useState([]);
  const collectData = () => {
    const allData = realm.objects('Product').filtered(`category = ${category}`);
    setData(allData);
  };
  useEffect(() => {
    const productPage = navigation.addListener('focus', () => {
      collectData();
    });
    return productPage;
  }, []);
  return (
    <View style={styles.mainContainer}>
      <FlatList
        data={data}
        contentContainerStyle={styles.flatListContainer}
        keyExtractor={item => item.id}
        renderItem={({item}) => {
          return (
            <TouchableOpacity style={styles.itemButton}>
              <View style={styles.productContainer}>
                <Image style={styles.image} source={{uri: item.imagePath}} />
                <View style={styles.textContainer}>
                  <Text style={styles.title}>{item.productName}</Text>
                  <Text style={styles.text}>{item.description}</Text>
                  <Text style={styles.text}>$ {item.price}</Text>
                </View>
              </View>
              <TouchableOpacity>
                <Icon name="shoppingcart" type="antdesign" size={30} />
              </TouchableOpacity>
            </TouchableOpacity>
          );
        }}
      />
    </View>
  );
};

export default ShowProductScreen;

const styles = StyleSheet.create({
  mainContainer: {
    flex: 1,
    backgroundColor: 'white',
  },
  flatListContainer: {
    padding: 8,
  },
  itemButton: {
    margin: 8,
    padding: 16,
    borderColor: '#7CAF58',
    borderWidth: 1,
    borderRadius: 10,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  productContainer: {
    flex: 1,
    flexDirection: 'row',
  },
  image: {
    width: 100,
    height: 100,
  },
  textContainer: {
    flex: 1,
    marginLeft: 16,
    justifyContent: 'center',
  },
  title: {
    color: 'black',
    fontSize: 18,
    fontWeight: 'bold',
  },
  text: {
    color: 'black',
    fontSize: 16,
  },
});

解决方案

1. 修复参数读取与未定义处理

ShowProductScreen存在两个问题:未解构navigation导致useEffect中报错,以及未处理route.params为undefined的情况。修改代码如下:

const ShowProductScreen = props => {
  const { route, navigation } = props; // 解构navigation
  const category = route.params?.categoryId; // 使用可选链避免params为undefined时报错
  const [data, setData] = useState([]);

  const collectData = () => {
    if (!category) return; // 无有效分类ID时终止查询
    const allData = realm.objects('Product').filtered(`category = ${category}`);
    setData(allData);
  };

  useEffect(() => {
    const productPage = navigation.addListener('focus', () => {
      collectData();
    });
    return productPage;
  }, [category]); // 添加category为依赖,参数变化时重新执行查询

  // 无分类ID时显示提示
  if (!category) {
    return (
      <View style={styles.mainContainer}>
        <Text style={{ textAlign: 'center', marginTop: 20, fontSize: 16 }}>请从分类页面进入商品列表</Text>
      </View>
    );
  }

  return (
    // 原返回内容保持不变
  );
};

2. 检查导航栈配置

确认导航栈中注册的页面名称为ShowProduct,与HomeScreen中navigation.navigate('ShowProduct')的名称完全一致,名称不匹配会导致参数无法传递。

3. 修正FlatList的key属性

HomeScreen中的FlatList使用key={3}是错误用法,直接移除该属性即可,keyExtractor已经能保证每个item的key唯一:

<FlatList
  data={categoryList}
  // 移除key={3}
  numColumns={3}
  keyExtractor={item => item.id}
  // 其他属性保持不变
/>

内容的提问来源于stack exchange,提问作者Eric Leonardo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:32:45