Using edamam api to get recipes. I am trying to use filter. It works with single filter but if I use multiple filter, giving error. Error is
react_devtools_backend_compact.js:13851 Error fetching recipes:
AxiosError {message: ‘Request failed with status code 400’, name: ‘AxiosError’, code: ‘ERR_BAD_REQUEST’, config: {…}, request: XMLHttpRequest, …}
code
:
“ERR_BAD_REQUEST”
config
:
{transitional: {…}, adapter: Array(3), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
message
:
“Request failed with status code 400”
name
:
“AxiosError”
request
:
XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
response
:
{data: {…}, status: 400, statusText: ”, headers: AxiosHeaders, config: {…}, …}
//components/SearchBar.tsx
"use client"
import PrimaryButton from '@/components/PrimaryButton';
import { Box, Button, Card, CardContent, TextField, Typography } from '@mui/material';
import React, { useState } from 'react';
interface SearchBarProps {
onSearch: (query: string , filters: { diet: string[] }) => void;
}
const SearchBar: React.FC<SearchBarProps> = ({ onSearch }) => {
const [query, setQuery] = useState('');
const [error, setError] = useState('');
// Filter state
const [dietFilter, setDietFilter] = useState<string[]>([]);
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!query.trim()) {
setError('Search query must not be null or empty');
return;
}
setError(''); // Clear error if query is valid
console.log("Search query:", query); // Debug statement
onSearch(query, { diet: dietFilter });
};
const handleDietChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { value, checked } = event.target;
setDietFilter((prevDietFilter) =>
checked ? [...prevDietFilter, value] : prevDietFilter.filter((diet) => diet !== value)
);
};
return (
<>
<Box display="flex" justifyContent="center" alignItems="center" minHeight="80vh">
<Card sx={{ maxWidth: 500, width: '100%', p: 2 }}>
<CardContent>
<Typography variant="h6" component="h6" gutterBottom>
Find the recipe
</Typography>
<Box mt={2} display="flex" alignItems="center">
<form onSubmit={handleSubmit}>
<TextField
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search for recipes"
variant="outlined"
fullWidth
sx={{ mb: 2 }}
error={Boolean(error)} // Show error state
helperText={error} // Display the error message
/>
<Box mb={2}>
<Typography variant="subtitle1">Diet</Typography>
<label>
<input type="checkbox" value="low-carb" onChange={handleDietChange} /> Low-Carb
</label>
<label style={{ marginLeft: '10px' }}>
<input type="checkbox" value="high-protein" onChange={handleDietChange} /> High-Protein
</label>
</Box>
<PrimaryButton type="submit" variant="contained">Search</PrimaryButton>
</form>
</Box>
</CardContent>
</Card>
</Box>
</>
);
};
export default SearchBar;
api.tsx
const API_URL = 'https://api.edamam.com/api/recipes/v2';
const APP_ID = process.env.NEXT_PUBLIC_APP_ID;
const APP_KEY = process.env.NEXT_PUBLIC_APP_KEY;
export const fetchRecipes = async (query: string, filters: FetchRecipesFilters = {}): Promise<Recipe[]> => {
if (!query) {
throw new Error('Search query must not be null or empty');
}
try {
// Debug: Log the query and filters
console.log('Query:', query);
console.log('Filters:', filters);
const params: Record<string, string> = {
type: 'public',
q: query,
app_id: APP_ID!,
app_key: APP_KEY!,
};
// If diet filters are provided, add them to the params
if (filters.diet && filters.diet.length > 0) {
params.diet = filters.diet.join(','); // Join filters with a comma
}
// Debug: Log the params being sent to the API
console.log('Request Params:', params);
const response = await axios.get<ApiResponse>(API_URL, {
params,
});
if (!response.data.hits) {
throw new Error('No recipes found');
}
return response.data.hits.map((hit) => hit.recipe);
} catch (error) {
console.error('Error fetching recipes:', error);
return [];
}
};
searchcontent
interface RecipeProp {
uri: string;
label: string;
image: string;
images: Images;
ingredientLines: string[];
}
export default function RecipeSearchContent() {
const [recipes, setRecipes] = React.useState<RecipeProp[]>([]);
const [isMounted, setIsMounted] = useState(true);
useEffect(() => {
setIsMounted(true);
return () => {
setIsMounted(false);
};
}, []);
const handleSearch = useCallback(async (query: string , filters: FetchRecipesFilters) => {
try {
// Fetch recipes from the API
const results: RecipeProp[] = await fetchRecipes(query, filters);
// If the component is still mounted, update the state
if (isMounted) {
setRecipes(results);
}
} catch (error) {
console.error("Error fetching recipes:", error);
}
}, [isMounted]);
return (
<Container>
<SearchBar onSearch={handleSearch} />
<RecipeListContent recipes={recipes} />
</Container>
);
}