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([]);
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 (
Best Selling Wines
setSearchTerm(e.target.value)}
/>
Rank
Wine Name
Vintage
Revenue
{filteredWines.map((wine) => (
{wine.rank}
{wine.name}
{wine.vintage}
GBP {wine.revenue.toFixed(2)}
))}
);
};
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);
});
Gcobani MkontwanaPosted Oct 20, 2024, 5:28 AM
Hi Paul
The APi response format is as follows
The front end still has that problem even now, followed all the steps.
Tuhin PaulPosted Oct 20, 2024, 4:18 AM
Check API Response Format
Based on your backend response, the data returned looks :
In your frontend, you're assuming
response.data.bestSellingWinescontains the data array, but there might be cases where the structure is different (for example,response.datamight not containbestSellingWines).Add a check to log
response.datato confirm the structure:Tuhin PaulPosted Oct 20, 2024, 4:16 AM
You can add more logging to see exactly what you're receiving from the server before setting the state:
Check if you are calling :
On the backend, make sure the
getBestSellingWinesfunction is returning the expected structure. You might want to add validation there to ensure that the response contains thebestSellingWineskey as an array.