Create a Food Reciepe App using React-Native
In this React-Native article, we will be developing an interactive Food Recipe Application. In this application, the users can be able to search for any food recipe in the search box. Then, according to the search query, the results will be fetched through an API and will be displayed in the application itself. Along with this, the user can also be able to View the Entire detailed recipe on the respective website and also can be able to send the recipe URL to other users in the form of mail.
Preview of final output: Let us have a look at how the final output will look like.
Prerequisites
Approach to Creating Food Recipe App
The below code snippet is entirely built in React Native, which is the user-friendly, interactive implementation of the Food Recipe Application. Here, we have used the useState hook to manage the states of various components in the application and the useEffect hook to properly display the food items in the application. In this application, there is an input box that takes the Food input from the user, according to the input the food recipe is fetched from the API and is displayed in the form of interactive cards. Users can click on the View Recipe link to get detailed information about the specific recipe. Also, the user can click on the Share Recipe to share the link of receive to the user in the form of Mail.
Steps to install & configure React Native:
Step 1: Create a react native application by using this command:
npx create-expo-app food-app
Step 2: After creating your project folder, i.e. food-app, use the following command to navigate to it:
cd food-app
Step 3: Install required modules via the following command in Terminal.
npm install react-native-svg
The updated dependencies in package.json file will look like:
"dependencies": {
"expo": "~49.0.15",
"expo-status-bar": "~1.6.0",
"react": "18.2.0",
"react-native": "0.72.6",
"react-native-svg": "^14.0.0"
},
Project Structure
Example: Implementation of the above approach using React Native. Functionalities contain files as follows:
- App.js: This is the main app component which calls another component in it. In this code, the Food Recipe has been fetched according to the user input.
- Food.js: In this code snippet file the implementation of displaying the food recipes, viewing the detailed recipe on the respective website, and sharing the recipe is been implemented.
Javascript
//App.js import React, { useEffect, useState } from 'react' ; import { View, Text, TextInput, TouchableOpacity, ScrollView, ActivityIndicator, RefreshControl } from 'react-native' ; import Food from './Food' ; const App = () => { const APP_ID = 'YOUR OWN API ID' ; const APP_KEY = 'YOUR OWN API Key' ; const [food_r, setfood_r] = useState([]); const [search_food, setSearch_food] = useState( '' ); const [search, setSearch] = useState( 'pizza' ); const [showFood, setShowFood] = useState( false ); useEffect(() => { getFood(); }, [search]); const getFood = async () => { try { setShowFood( true ); const response = await fetch( `https: //api.edamam.com/search?q=${search}&app_id=${APP_ID}&app_key=${APP_KEY}` ); const data = await response.json(); setfood_r(data.hits); setShowFood( false ); } catch (error) { console.error( 'Error fetching recipes:' , error); setShowFood( false ); } }; const searchBarUpdate = (text) => { setSearch_food(text); }; const searchFunction = () => { setSearch(search_food); setSearch_food( '' ); }; const refreshFunction = () => { getFood(); }; return ( <View style={{ flex: 1, backgroundColor: '#F5F5F5' , paddingTop: 30 }}> <View style={{ backgroundColor: '#32CD32' , padding: 20, marginBottom: 20, alignItems: 'center' }}> <Text style={{ fontSize: 32, color: 'white' , fontWeight: 'bold' , textShadowColor: 'rgba(0, 0, 0, 0.75)' , textShadowOffset: { width: 2, height: 2 }, textShadowRadius: 5 }}> GFG Food Recipe App </Text> </View> <View style={{ marginHorizontal: 20, marginBottom: 20 }}> <TextInput style={{ height: 40, borderColor: '#E0E0E0' , borderWidth: 1, borderRadius: 8, padding: 8, backgroundColor: 'white' , marginBottom: 10,}} placeholder= "Search for food recipes..." placeholderTextColor= "#757575" value={search_food} onChangeText={searchBarUpdate}/> <TouchableOpacity style={{ backgroundColor: '#FF6F61' , padding: 12, borderRadius: 8, alignItems: 'center' ,}} onPress={searchFunction}> <Text style={{ color: 'white' , fontWeight: 'bold' }}> Search Food Recipe </Text> </TouchableOpacity> </View> {showFood ? ( <ActivityIndicator size= "large" color= "#FF6F61" style={{ marginTop: 20 }} /> ) : ( food_r.length === 0 ? ( <Text style={{ textAlign: 'center' , color: '#757575' , marginTop: 20 }}> No recipes found. Try a different search term. </Text> ) : ( <ScrollView style={{ marginHorizontal: 20 }} refreshControl={ <RefreshControl refreshing={showFood} onRefresh={refreshFunction}/>}> {food_r.map((recipe) => ( <Food key={recipe.recipe.label} recipe={recipe.recipe} /> ))} </ScrollView> ) )} </View> ); }; export default App; |
Javascript
//Food.js // RecipeCard.jsx import React from 'react' ; import { View, Text, Image, TouchableOpacity, Linking } from 'react-native' ; import Svg, { Path } from 'react-native-svg' ; const Food = ({ recipe }) => { const openFood = () => { if (recipe.url) { Linking.openURL(recipe.url); } }; const shareFood = () => { if (recipe.url) { Linking.openURL( `mailto:?subject=Check%20out%20this%20recipe&body=${recipe.url}`); } }; return ( <View style={{ backgroundColor: '#FFF' , borderRadius: 8, overflow: 'hidden' , marginBottom: 16, shadowColor: '#000' , shadowOffset: { width: 0, height: 2,}, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5,}}> <View style={{ position: 'relative' }}> <Image style={{ width: '100%' , height: 200, borderTopLeftRadius: 8, borderTopRightRadius: 8 }} source={{ uri: recipe.image }} resizeMode= "cover" /> <View style={{ position: 'absolute' , top: 8, left: 8, backgroundColor: '#FF4081' , paddingVertical: 4, paddingHorizontal: 8, borderRadius: 4, color: 'white' ,}}> <Text style={{ color: 'white' }}> {recipe.dishType[0]} </Text> </View> </View> <View style={{ padding: 16 }}> <Text style={{ fontSize: 22, fontWeight: 'bold' , marginBottom: 8, color: '#333' }}> {recipe.label} </Text> <View style={{ marginBottom: 8 }}> <Text style={{ fontWeight: 'bold' , color: '#757575' }}> Ingredients: </Text> {recipe.ingredientLines.map((ingredient, index) => ( <Text key={index} style={{ paddingLeft: 16, color: '#333' }}> {ingredient} </Text> ))} </View> <View style={{ flexDirection: 'row' , justifyContent: 'space-between' , alignItems: 'center' }}> <TouchableOpacity onPress={openFood}> <View style={{ backgroundColor: '#FF4081' , padding: 6, borderRadius: 8, alignItems: 'center' ,}}> <Svg width= "24" height= "24" viewBox= "0 0 24 24" fill= "none" stroke= "white" strokeWidth= "2" strokeLinecap= "round" strokeLinejoin= "round" > <Path d= "M10 12H5l7-7 7 7h-5v6h-4v-6z" ></Path> </Svg> <Text style={{ color: 'white' , fontWeight: 'bold' }}> View Recipe </Text> </View> </TouchableOpacity> <TouchableOpacity onPress={shareFood}> <View style={{ backgroundColor: '#FF6F61' , padding: 6, borderRadius: 8, alignItems: 'center' , marginLeft: 10,}}> <Svg width= "24" height= "24" viewBox= "0 0 24 24" fill= "none" stroke= "white" strokeWidth= "2" strokeLinecap= "round" strokeLinejoin= "round" > <Path d= "M24 12l-9-8v6H2v4h13v6z" ></Path> </Svg> <Text style={{ color: 'white' , fontWeight: 'bold' }}> Share Recipe </Text> </View> </TouchableOpacity> </View> </View> </View> ); }; export default Food; |
Steps to run the application:
Step 1: Run the App via the following command.
npx expo start
Step 2: Run the command according to your Operating System.
- Android
npx react-native run-android
- IOS
npx react-native run-ios