The App component uses the BrowserRouter library to render the Home component when the path = "/", the searchResults component is rendered when the path = "/seach:searchQuery". All this is functioning as expected. The Home component itself renders my Navbar component, which in turn renders my Searchbar component. The Searchbar component sets the url on submit to "/search/searchquery".
For some unknown reason is the seacquery variable not accesible in my searchResults components, and printing it returns "undefined". If anyone can help me figuring out how I pass that variable correctly to the searchResults component than that would be greatly appreciated. I removed most of my styles code to not make the post too long.
App Component:
import React from 'react';
// eslint-disable-next-line
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import SearchResults from './components/SearchResults';
const App = () => {
const searchQuery = new URLSearchParams(window.location.search).get('searchQuery');
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path='/search/:searchQuery' element={<SearchResults searchQuery={searchQuery} />} />
<Route path="*" element={<h1>404 - Not Found</h1>} />
</Routes>
);
};
export default App;
The Home Component:
import React from 'react'
import Rectangle from '../images/Rectangle.png'
import HeroImg from '../images/heroImg.png'
import { BsArrowRight } from 'react-icons/bs'
import { useState, useEffect } from 'react'
import { FaTelegramPlane } from 'react-icons/fa'
import { FaFacebook } from 'react-icons/fa'
import { FaInstagram } from 'react-icons/fa'
import { FaTwitter } from 'react-icons/fa'
import Navbar from './Navbar'
const Home = () => {
const [vegetarianRecipes, setVegetarianRecipes] = useState([]);
const [searchQuery, setSearchQuery] = useState('');
const handleSearchSubmit = (searchQuery) => {
setSearchQuery(searchQuery);
};
useEffect(() => {
async function fetchVegetarianRecipes() {
const response = await fetch(
"https://www.themealdb.com/api/json/v1/1/filter.php?c=vegetarian"
);
const data = await response.json();
const threeRecipes = data.meals.slice(1, 4);
setVegetarianRecipes(threeRecipes);
}
fetchVegetarianRecipes();
}, []);
const [beefRecipes, setbeefRecipes] = useState([]);
useEffect(() => {
async function fetchbeefRecipes() {
const response = await fetch(
"https://www.themealdb.com/api/json/v1/1/filter.php?c=beef"
);
const data = await response.json();
const threeRecipes = data.meals.slice(2, 5);
setbeefRecipes(threeRecipes);
}
fetchbeefRecipes();
}, []);
const [seafoodRecipes, setseafoodRecipes] = useState([]);
useEffect(() => {
async function fetchseafoodRecipes() {
const response = await fetch(
"https://www.themealdb.com/api/json/v1/1/filter.php?c=seafood"
);
const data = await response.json();
const threeRecipes = data.meals.slice(2, 5);
setseafoodRecipes(threeRecipes);
}
fetchseafoodRecipes();
}, []);
const [dessertRecipes, setdessertRecipes] = useState([]);
useEffect(() => {
async function fetchdessertRecipes() {
const response = await fetch(
"https://www.themealdb.com/api/json/v1/1/filter.php?c=dessert"
);
const data = await response.json();
const threeRecipes = data.meals.slice(2, 5);
setdessertRecipes(threeRecipes);
}
fetchdessertRecipes();
}, []);
return (
<>
<Navbar onSearchSubmit={handleSearchSubmit}/>
<div className={styles.heroContainer}>
<img src={HeroImg} alt='hero' className={styles.hero} />
<div className={styles.heroOverlay}>
<div className={styles.heroOverlay__text}>
<h1>Overcome your winter dip with these delicious classics...</h1>
</div>
<div className={styles.heroOverlay__button}>
<BsArrowRight size={40} />
</div>
</div>
</div>
<div className={styles.bar}></div>
<div className={styles.CategoryContainer}>
<div className={styles.categoryTitle}>Healthy Recipes</div>
<div className="flex flex-wrap justify-between">
{vegetarianRecipes.map((recipe) => (
<div className={styles.categoryCard} key={recipe.idMeal}>
<img src={recipe.strMealThumb} alt={recipe.strMeal} />
<div className={styles.categoryCardOverlay}>
<div className={styles.categoryCardOverlayText}>
{recipe.strMeal}
</div>
<div className={styles.categoryCardOverlayButton}>
<BsArrowRight size={24} />
</div>
</div>
</div>
))}
</div>
</div>
<div className={styles.moreContainer}>
<div className={styles.more}><h1>More Healthy Recipes...</h1></div>
</div>
<div className={styles.bar}></div>
<div className={styles.CategoryContainer}>
<div className={styles.categoryTitle}>Beef Recipes</div>
<div className="flex flex-wrap justify-between">
{beefRecipes.map((recipe) => (
<div className={styles.categoryCard} key={recipe.idMeal}>
<img src={recipe.strMealThumb} alt={recipe.strMeal} />
<div className={styles.categoryCardOverlay}>
<div className={styles.categoryCardOverlayText}>
{recipe.strMeal}
</div>
<div className={styles.categoryCardOverlayButton}>
<BsArrowRight size={24} />
</div>
</div>
</div>
))}
</div>
</div>
<div className={styles.moreContainer}>
<div className={styles.more}><h1>More Beef Recipes...</h1></div>
</div>
<div className={styles.banner}>
<div className={styles.banner__text}>
<h1>Get the best recipes delivered to your inbox</h1>
</div>
<div className={styles.banner__button}>
<FaTelegramPlane size={74} />
</div>
</div>
<div className={styles.CategoryContainer}>
<div className={styles.categoryTitle}>Seafood Recipes</div>
<div className="flex flex-wrap justify-between">
{seafoodRecipes.map((recipe) => (
<div className={styles.categoryCard} key={recipe.idMeal}>
<img src={recipe.strMealThumb} alt={recipe.strMeal} />
<div className={styles.categoryCardOverlay}>
<div className={styles.categoryCardOverlayText}>
{recipe.strMeal}
</div>
<div className={styles.categoryCardOverlayButton}>
<BsArrowRight size={24} />
</div>
</div>
</div>
))}
</div>
</div>
<div className={styles.moreContainer}>
<div className={styles.more}><h1>More Seafood Recipes...</h1></div>
</div>
<div className={styles.bar}></div>
<div className={styles.CategoryContainer}>
<div className={styles.categoryTitle}>Dessert Recipes</div>
<div className="flex flex-wrap justify-between">
{dessertRecipes.map((recipe) => (
<div className={styles.categoryCard} key={recipe.idMeal}>
<img src={recipe.strMealThumb} alt={recipe.strMeal} />
<div className={styles.categoryCardOverlay}>
<div className={styles.categoryCardOverlayText}>
{recipe.strMeal}
</div>
<div className={styles.categoryCardOverlayButton}>
<BsArrowRight size={24} />
</div>
</div>
</div>
))}
</div>
</div>
<div className={styles.moreContainer}>
<div className={styles.more}><h1>More Dessert Recipes...</h1></div>
</div>
<div className={styles.bar}></div>
<div className={styles.footer}>
<div className={styles.footerMain}>
<div className={styles.text}>
<div className={styles.footerMainTitle}>
<h1>Recipe App</h1>
</div>
<div className={styles.footerMainParagraph}>
<p>Recipes you want to make. Cooking advice that works.</p>
</div>
</div>
<div className={styles.footerLinks}>
<div className={styles.footerLinksTitle}>
<h2 className={styles.footerMainLinksTitle}>Quick Links</h2>
</div>
<div className={styles.footerLinksList}>
<ul>
<li>
<p className={styles.footerMainLinksList} href="#">About Us</p>
</li>
<li>
<p className={styles.footerMainLinksList} href="#">Contact Us</p>
</li>
<li>
<p className={styles.footerMainLinksList} href="#">Privacy Policy</p>
</li>
<li>
<p className={styles.footerMainLinksList} href="#">Terms & Conditions</p>
</li>
</ul>
</div>
</div>
<div className={styles.footerSocial}>
<div className={styles.footerSocialTitle}>
<h2>Connect with us</h2>
</div>
<div className={styles.footerSocialIcons}>
<p href="#"><FaFacebook size={28} /></p>
<p href="#"><FaInstagram size={28} /></p>
<p href="#"><FaTwitter size={28} /></p>
</div>
</div>
</div>
<div className={styles.footerBottom}>
<p>© 2023 Recipe App. All rights reserved.</p>
</div>
</div>
</>
);
};
export default Home
Navbar component:
import React from 'react'
import { BsGithub } from 'react-icons/bs'
import SearchBar from './SearchBar'
import Rectangle from '../images/Rectangle.png'
import { useState } from 'react'
const Navbar = ({onSearchSubmit}) => {
const [searchQuery, setSearchQuery] = useState('');
const handleSearchSubmit = (searchQuery) => {
setSearchQuery(searchQuery);
};
return (
<>
<div className={styles.container}>
<img className={styles.logoDiv} src={Rectangle} alt='decoration' />
<div className={styles.navbar}>
<SearchBar onSearchSubmit={handleSearchSubmit} />
<div className={styles.gitHub}>
<BsGithub size={32} />
</div>
</div>
</div>
</>
)
}
export default Navbar
Searchbar component:
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { AiOutlineSearch } from 'react-icons/ai';
const styles = {
searchbar: `w-1/2 h-10 flex justify-between items-center bg-[#D9D9D9] mx-auto rounded-full mx-auto absolute left-0 right-0`,
searchbar__input: `px-5 h-10 w-full flex justify-center items-center bg-[#D9D9D9] rounded-full focus:outline-none active:outline-none `,
searchbar__button: `flex justify-center items-center px-3`,
};
const SearchBar = ({onSearchSubmit}) => {
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault();
const searchQuery = event.target.elements.searchInput.value;
onSearchSubmit(searchQuery);
navigate(`/search/${searchQuery}`)
};
return (
<div className={styles.searchbar}>
<form onSubmit={handleSubmit} className={styles.searchbar__input}>
<input
type="text"
placeholder="Search recipes..."
className={styles.searchbar__input}
name="searchInput"
/>
<button className={styles.searchbar__button} type="submit">
<AiOutlineSearch size={24} />
</button>
</form>
</div>
);
}
export default SearchBar;
SearchResults Component:
import React, { useEffect } from 'react';
import { useState } from 'react';
import Navbar from './Navbar';
const styles = {
container: `w-full h-full flex bg-[#FFF] flex-col relative `,
logoDiv: `flex justify-center items-center bg-transparent z-20 absolute -rotate-20 m:w-[20%] w-[35%] lg:w-[20%] xl:w-[20%] `,
navbar: `w-full h-20 flex items-center px-10 `,
searchbar: `w-1/2 h-10 flex justify-between items-center bg-[#D9D9D9] mx-auto rounded-full mx-auto absolute left-0 right-0`,
searchbar__input: `px-5 h-10 w-full flex justify-center items-center bg-[#D9D9D9] rounded-full focus:outline-none `,
searchbar__button: `flex justify-center items-center px-3`,
gitHub: ` flex justify-center items-center absolute right-7 top-7`,
recipeContainer: `w-full h-full grid grid-cols-4 grid-rows-4 gap-4 p-10`,
text: `text-2xl font-bold text-black`,
};
function SearchResults({searchQuery}) {
const setSearchQuery = useState(searchQuery);
const handleSearchSubmit = (searchQuery) => {
setSearchQuery(searchQuery);
};
useEffect(() => {
console.log(searchQuery);
}, [searchQuery]);
return (
<>
<Navbar onSearchSubmit={handleSearchSubmit} />
<div className={styles.recipeContainer}>
<div>tetststs</div>
<h1 className={styles.text}>test{searchQuery}</h1>
</div>
</>
);
}
export default SearchResults;