skip to Main Content

I’m working on a React Native app where I’m using React Navigation to navigate between screens. I have a Drawer component that contains a "Give me a Random Recipe!!" button. When the button is pressed, I want to navigate to the RecipeScreen and pass a random recipe object as well as its corresponding category and title.

However, I’m facing an issue where the category prop in the RecipeScreen is always undefined, even though I’m passing it correctly from the DrawerContainer. I have checked the logs, and the category is correctly logged in the DrawerContainer component before navigation.

I have simplified the relevant code snippets for both components below:

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>
  );
}

I get an error on this line when switching screens:

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

because

const category = route.params.category;

is undefined when I switch from the drawer screen to the recipe screen.

I would greatly appreciate any insights or suggestions on how to correctly pass the category prop from Drawer to RecipeScreen. Thank you in advance!

2

Answers


  1. The issue you’re facing is likely due to the fact that you’re trying to access the category prop in RecipeScreen using route.params.category, but it seems that you’re passing the category as a separate prop named category in your navigation.navigate call in the Drawer component.

    To resolve this, you can modify your handleNavigate function in the Drawer component to pass the category prop directly instead of including it in the navigation.navigate call:

    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();
    };
    

    Then, in your RecipeScreen, you can access the category prop directly from route.params:

    const category = route.params.category; // Access category from route.params
    
    // ...
    
    <Text style={styles.category}>
      {category && getCategoryName(item.categoryId).toUpperCase()}
    </Text>
    

    Make sure to double-check the correctness of your getCategoryName function and ensure that it returns the expected category name based on the provided categoryId.

    By making these changes, you should be able to correctly access the category prop in your RecipeScreen component and display the category name.

    Login or Signup to reply.
  2. You are passing the randomRecipe, category and title in the name of item from Drawer.js correctly, But, You have to change the props to access the prop in your RecipeScreen.js like this ,

    export default function RecipeScreen(props) {
    
      const { navigation, route } = props;
    
      const { category } = route.params.item; // Destructure the category from item
    
      const title = route.params.title; 
    
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search