Hi Team
I have a mean stack app, basically my front end suppose when type 'wine or vintage' as search field name must return or fetch data back to front end. Now the response when debugging its receving this data back;
(index):68 Uncaught (in promise) TypeError: wines.filter is not a function at fetchWines ((index):68:37)
import React, { useState, useEffect } from 'react'; import axios from 'axios'; import 'bootstrap/dist/css/bootstrap.min.css'; import '@fortawesome/fontawesome-free/css/all.min.css'; import './App.css'; const App: React.FC = () => { const [wines, setWines] = useState<any[]>([]); const [criteria, setCriteria] = useState('revenue'); const [searchTerm, setSearchTerm] = useState(''); useEffect(() => { const fetchWines = async () => { try { const response = await axios.get( `/api/best-selling-wines?criteria=${criteria}&searchTerm=${searchTerm}`, { headers: { 'Cache-Control': 'no-cache' }, } ); console.log('Response:', response); console.log('Response data:', response.data); if (response.headers['content-type'].includes('application/json')) { const winesData = response.data.bestSellingWines; console.log('Best Selling Wines:', winesData); setWines(Array.isArray(winesData) ? winesData : []); } else { console.error('Unexpected response:', response.data); } } catch (error) { if (axios.isAxiosError(error)) { console.error('Error fetching data:', error.response ? error.response.data : error.message); } else { console.error('Unexpected error:', error); } } }; fetchWines(); }, [criteria, searchTerm]); const filteredWines = Array.isArray(wines) ? wines.filter( (wine) => wine.name?.toLowerCase().includes(searchTerm.toLowerCase()) || wine.vintage?.toString().includes(searchTerm) ) : []; return ( <div className="container"> <nav className="navbar navbar-expand-lg navbar-light bg-light"> <a className="navbar-brand" > Wine Stats </a> <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav"> <li className="nav-item"> <button className="nav-link btn" onClick={() => setCriteria('revenue')}> By Revenue </button> </li> <li className="nav-item"> <button className="nav-link btn" onClick={() => setCriteria('quantity')}> By # Bottles Sold </button> </li> <li className="nav-item"> <button className="nav-link btn" onClick={() => setCriteria('orders')}> By Orders </button> </li> </ul> </div> </nav> <h1 className="mt-4 text-center">Best Selling Wines</h1> <div className="search-bar-container"> <div className="search-bar"> <input id="searchBar" type="text" className="form-control" placeholder="Search by name or vintage..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> <span className="search-icon"> <i className="fas fa-search"></i> </span> </div> </div> <table className="table mt-3"> <thead> <tr> <th>Rank</th> <th>Wine Name</th> <th>Vintage</th> <th>Revenue</th> </tr> </thead> <tbody> {filteredWines.map((wine) => ( <tr key={wine.masterWineId} className={wine.isTop10 ? 'table-success' : wine.isBottom10 ? 'table-danger' : ''} > <td>{wine.rank}</td> <td>{wine.name}</td> <td>{wine.vintage}</td> <td>GBP {wine.revenue.toFixed(2)}</td> </tr> ))} </tbody> </table> </div> ); }; export default App;
//back end response
isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] } Incoming request: [Object: null prototype] { criteria: 'revenue' } Wines data: { bestSellingWines: [ { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 402.6, quantity: 10, orders: 1, price: 40.26, rank: 1, isTop10: true, isBottom10: false }, { masterWineId: 2, name: 'Domaine Leflaive', vintage: 2018, revenue: 240, quantity: 2, orders: 1, price: 120, rank: 2, isTop10: false, isBottom10: false }, { masterWineId: 1, name: 'Château Montclair', vintage: 2020, revenue: 203.8, quantity: 5, orders: 1, price: 40.76, rank: 3, isTop10: false, isBottom10: false } ], masterWines: [ { id: 1, name: 'Château Montclair', vintage: 2020 }, { id: 2, name: 'Domaine Leflaive', vintage: 2018 }, { id: 1, name: 'Château Montclair', vintage: 2020 } ] }
// server.ts
import Fastify from 'fastify'; import cors from '@fastify/cors'; import { setupDatabase, getBestSellingWines } from './data'; const fastify = Fastify(); fastify.register(cors, { origin: 'http://localhost:5173', methods: ['GET'], allowedHeaders: ['Content-Type'], }); interface QueryParams { criteria?: 'revenue' | 'quantity' | 'orders'; searchTerm?: string; } fastify.get<{ Querystring: QueryParams }>('/api/best-selling-wines', async (request, reply) => { console.log('Incoming request:', request.query); const { criteria = 'revenue', searchTerm = '' } = request.query; try { const wines = await getBestSellingWines(criteria, searchTerm); console.log('Wines data:', wines); reply.header('Content-Type', 'application/json').send({ bestSellingWines: wines.bestSellingWines }); } catch (error) { console.error('Error fetching wines:', error); reply.code(500).header('Content-Type', 'application/json').send({ error: 'An error occurred', details: error.message }); } }); setupDatabase() .then(() => { console.log('Database setup complete'); fastify.listen({ port: 3000, host: 'localhost' }, (err, address) => { if (err) { console.error('Server listen error:', err); process.exit(1); } console.log(`Server listening at ${address}`); }); }) .catch((err) => { console.error('Error setting up database:', err); });