NodeJS 使用React Navigation在屏幕之间传递props

ijnw1ujt  于 2023-06-22  发布在  Node.js
关注(0)|答案(1)|浏览(129)

我正在开发一个React Native应用程序,我使用React Navigation在屏幕之间导航。我有一个抽屉组件,其中包含一个“给予我一个随机食谱!!”按钮。当按钮被按下时,我想导航到RecipeScreen并传递一个随机的食谱对象及其相应的类别和标题。
然而,我遇到了一个问题,RecipeScreen中的类别属性总是未定义的,即使我从DrawerContainer正确地传递了它。我已经检查了日志,在导航之前,类别正确地记录在DrawerContainer组件中。
我简化了下面两个组件的相关代码片段:
Drawer.js:

import React, { useEffect } from "react";
import { getCategoryById } from "../../data/API";

const Drawer = () => {
  const navigation = useNavigation();

  useEffect(() => {
    // Fetch random recipe here if needed
  }, []);

  const handleNavigate = () => {
    const randomRecipe = {}; // Replace with the random recipe object
    const category = getCategoryById(randomRecipe.categoryID);
    const title = category ? category.name : "";

    navigation.navigate("Recipe", { item: randomRecipe, category, title });

    navigation.closeDrawer();
  };

  return (
    <View>
      <MenuButton
        title="Give me a Random Recipe!!"
        onPress={handleNavigate}
      />
    </View>
  );
};

DrawerContainer.propTypes = {
  navigation: PropTypes.shape({
    navigate: PropTypes.func.isRequired,
    closeDrawer: PropTypes.func.isRequired,
  }),
};

export default DrawerContainer;

RecipeScreen.js:

export default function RecipeScreen(props) {
  const { navigation, route } = props;

  const category = route.params.category;

  const title = item.title;

  const [activeSlide, setActiveSlide] = useState(0);
  const [recipeData, setRecipeData] = useState(null);

  const slider1Ref = useRef();

  useLayoutEffect(() => {
    navigation.setOptions({
      headerTransparent: true,
      headerLeft: () => (
        <BackButton
          onPress={() => {
            navigation.goBack();
          }}
        />
      ),
      headerRight: () => <View />,
    });
  }, []);

  const renderImage = ({ item }) => (
    <TouchableHighlight>
      <View style={styles.imageContainer}>
        <Image style={styles.image} source={{ uri: item }} />
      </View>
    </TouchableHighlight>
  );

  useEffect(() => {
    fetch('http://10.11.55.7:111/rest', {
      headers: {
        'Content-Type': 'application/json'
      }
    })
      .then(response => response.json())
      .then(data => {
        const matchedRecipe = data.find(recipe => recipe.recipeID === item.recipeId);
        if (matchedRecipe) {
          console.log(matchedRecipe.recipeID);
          setRecipeData(matchedRecipe);
        } else {
          console.log('No matching recipe found');
        }
      })
      .catch(error => {
        console.log('Fetch error:', error);
        // Handle the error here
      });
  }, []);

  return (
    <ScrollView style={styles.container}>
      <View style={styles.carouselContainer}>
        <View style={styles.carousel}>
          <Carousel
            ref={slider1Ref}
            data={item.photosArray}
            renderItem={renderImage}
            sliderWidth={viewportWidth}
            itemWidth={viewportWidth}
            inactiveSlideScale={1}
            inactiveSlideOpacity={1}
            firstItem={0}
            loop={false}
            autoplay={false}
            autoplayDelay={500}
            autoplayInterval={3000}
            onSnapToItem={(index) => setActiveSlide(0)}
          />
          <Pagination
            dotsLength={item.photosArray.length}
            activeDotIndex={activeSlide}
            containerStyle={styles.paginationContainer}
            dotColor="rgba(255, 255, 255, 0.92)"
            dotStyle={styles.paginationDot}
            inactiveDotColor="white"
            inactiveDotOpacity={0.4}
            inactiveDotScale={0.6}
            carouselRef={slider1Ref.current}
            tappableDots={!!slider1Ref.current}
          />
        </View>
      </View>
      <View style={styles.infoRecipeContainer}>
        <Text style={styles.infoRecipeName}>{item.title}</Text>
        <View style={styles.infoContainer}>
          {category && (
            <Text style={styles.category}>
              {getCategoryName(item.categoryId).toUpperCase()}
            </Text>
          )}
        </View>
      </View>
    </ScrollView>
  );
}

切换屏幕时,我在这一行得到一个错误:

{getCategoryName(item.categoryId).toUpperCase()}

因为

const category = route.params.category;

从抽屉屏幕切换到食谱屏幕时,未定义。
我将非常感谢任何关于如何正确地将类别 prop 从抽屉传递到RecipeScreen的见解或建议。感谢您的评分

uqjltbpv

uqjltbpv1#

您面临的问题可能是由于您试图使用route.params.category访问RecipeScreen中的类别属性,但似乎您在Drawer组件中的navigation.navigate调用中将类别作为名为category的单独属性传递。
要解决这个问题,您可以修改Drawer组件中的handleNavigate函数,以直接传递类别属性,而不是将其包含在navigation.navigate调用中:

const handleNavigate = () => {
  const randomRecipe = {}; // Replace with the random recipe object
  const category = getCategoryById(randomRecipe.categoryID);
  const title = category ? category.name : "";

  navigation.navigate("Recipe", {
    item: randomRecipe,
    category, // Pass the category prop separately
    title,
  });

  navigation.closeDrawer();
};

然后,在RecipeScreen中,您可以直接从route.params访问类别属性:

const category = route.params.category; // Access category from route.params

// ...

<Text style={styles.category}>
  {category && getCategoryName(item.categoryId).toUpperCase()}
</Text>

请确保仔细检查getCategoryName函数的正确性,并确保它根据提供的categoryId返回预期的类别名称。
通过进行这些更改,您应该能够正确访问RecipeScreen组件中的类别属性并显示类别名称。

相关问题