I’m new in Next and Typescript and can’t solve the issue, I have tried all possible options that found in the internet and thinking maybe the problem is that the answers were old and something have changed….
I’m getting this error in my restaurant website project while trying to make a categories filter for menu .
I was supposed to get categories from menu. I use Set to get unique categories from menu data and then I make an array from object uniqueCategoriesSet
(I just read in the internet that it can solve the issue with "TypeError: uniqueCategories.map is not a function " but it doesnt).
Before this I was just passing unuqieCategoriesSet to CategoriesButtons as a prop and there was the same issue and also another issue in CategoryButtons component: "Parameter ‘uniqueCategoriesSet’ implicitly has an ‘any’ type."
I’m using framework Next and Typescript
I really appressiate any help!
page.tsx:
"use client"
import React, {useEffect} from 'react'
import { menu } from '../data'
import Link from 'next/link'
import Image from 'next/image'
import CategoryButtons from '../components/CategoryButtons'
const MenuPage = () => {
const uniqueCategoriesSet = new Set<string>();
menu.forEach(item => {
uniqueCategoriesSet.add(item.cat);
});
const uniqueCategories: string[] = Array.from(uniqueCategoriesSet);
return (
<div className='p-4 '>
<h1 className='text-center'>Menu</h1>
<CategoryButtons {...uniqueCategories}/>
<div className=" flex flex-wrap">
{menu.map(item=>(
<div className=' w-full h-[60vh] flex flex-col items-center justify-center border-2 sm:w-1/2 md:w-1/3 lg:w-1/4'>
<div className='relative h-[60%] w-full '>
<Image src="/fruit-salad.png" alt="" fill className='object-contain'/>
</div>
<div className='p-4'>
<h1 className='font-bold'>{item.title}</h1>
<p>Desc</p>
<span className='font-bold'>Price</span>
</div>
</div>
))}
</div>
</div>
)
}
export default MenuPage
CategoryButtons.tsx:
import React from 'react'
const CategoryButtons = (uniqueCategories:string[]) => {
console.log(typeof(uniqueCategories));
return (
<div className='flex items-center gap-2 h-12'>
<button className='bg-green-600 p-1 text-sm text-white rounded-md'>All</button>
{uniqueCategories.map((item)=>(
<button className='bg-green-600 p-1 text-sm text-white rounded-md'>
{item}
</button>
))}
</div>
)
}
export default CategoryButtons
my data - menu:
interface Menu {
id: number;
cat: string;
title: string;
desc?: string;
img?: string;
};
export const menu:Menu[] = [
{
id: 1,
cat: "starters",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 2,
cat: "starters",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 3,
cat: "main",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 4,
cat: "main",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 5,
cat: "drinks",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 6,
cat: "drinks",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 7,
cat: "desserts",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
{
id: 8,
cat: "desserts",
title: "Fruit salad",
desc: "Strawberry, banana, avocado",
img: "/fruit-salad.png",
},
]
I just want to press buttons (CategoryButtons component) of menu categories (drinks, Main courses etc..) and be able to filter menu (MenuPage page)
I have tried passing a Set uniqueCategoriesSet to a CategoryButtons
Because I thought that the issue is that map function doesnt work with objects i decided to make an array from the unuqueCategoriesSet
I have tried passing an Array uniqueCategories to a CategoryButtons
(and i checked type of uniqueCategories, it is an object…)
I have tried changing the way I pass unuque Categories to CategoryButtons:
<CategoryButtons {...uniqueCategories}/> <CategoryButtons <CategoryButtons uniqueCategories={uniqueCategories}/>
I have tried to change parameters in CategoryButtons conponent:
const CategoryButtons = (uniqueCategoriesSet) const CategoryButtons = (uniqueCategoriesSet:[string])
3
Answers
Hi I come from Vue rather then React, but the spread on the component looks odd.
<CategoryButtons {…uniqueCategories} />: In this line, you are spreading the uniqueCategories array into the CategoryButtons component. However, you should pass an array as a prop, not spread its values. To pass an array as a prop, you should do it like this:
In the CategoryButtons component, make sure it handles the categories prop correctly. You can then map over the categories array to render buttons.
You should send the props like:
What is sent is a object with property
uniqueCat
. Read it like:Alternatively destructure it:
Ref: https://react.dev/learn/passing-props-to-a-component
There are couple of things that needs to be corrected in your code. Firstly, the functional component
CategoryButtons
accepts props which is always of type object. You cannot pass theuniqueCategories
array directly. It has to be one of the properties in the props object. Note that it can be named anything. Example below:And in the
page.tsx
file, you would pass the props as shown below:Hope it helps! here’s a link to the codesandbox where I solved your problem.