Reputation: 256
I'm learning React and I'm trying to create a dynamic Dropdown select. I'm importing the data from fetched API successfully from another component. I want to populate select option by category from the fetched data, which is an array of a single string either 'women', 'men' or 'kids' . What I want, is to have initially all data listed, to have 3 options for category strings and list only matching products according to the onChange event.
Now when I click to the select the whole app renders and can't see the bug.
Any help will be appreciated
Here is how API data looks like:
[
{
categories: [
'women'
],
variants: [
'white',
'black',
'green'
],
sizes: [
38,
39,
40
],
_id: '5f8edf08880a821cb8757d8a',
name: 'Nike Air',
description: 'Tennis court levitating sneaker',
img: 'https://source.unsplash.com/user/erondu/PGTO_A0eLt4',
price: 100,
__v: 1
}
]
Category component
import React, { useState } from 'react'
const Categories = ({ categories }: any) => {
const [category, setCategory] = useState('')
console.log('category', category)
return (
<>
<select
value={category}
onChange={(e) => setCategory(e.target.value)}
>
<option value="">Select</option>
{categories && categories.map((option: any) => (
<option key={option._id}
value={option.categories}
>
{option.categories}
</option>
))}
</select>
</>
)
}
export default Categories
Upvotes: 2
Views: 11504
Reputation: 4536
Try something like that:
// Categories Component
const Categories = ({ data }) => {
// You need an initial value if you like to show something when page first load
// assuming you know exactly how your data will look like
const [selected, setSelected] = React.useState(data[0].categories[0]);
const [selectedCategory, setSelectedCategory] = React.useState(data);
React.useEffect(() => {
// Filter out categories by selected option
const category = data.filter((item) => item.categories[0] === selected);
setSelectedCategory(category);
// Will change when data changes or another item selected
}, [data, selected]);
// Set selected option
const handleSelcet = (e) => {
setSelected(e.target.value);
};
return (
<React.Fragment>
<select onChange={handleSelcet}>
{data.map((item) =>
item.categories.map((category) => (
<option key={category} value={category}>
{category}
</option>
))
)}
</select>
{selectedCategory.map((category) => {
return (
<div key={category._id}>
<p>Name: {category.name}</p>
<p>Description: {category.description}</p>
<p>Price: {category.price}</p>
variants:
<ul>
{category.variants.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
<img src={category.img} alt="" />
</div>
);
})}
</React.Fragment>
)
}
// Data from API
const data = [
{
categories: ["women"],
variants: ["white", "black", "green"],
sizes: [38, 39, 40],
_id: "5f8edf08880a821cb8757d8a",
name: "Nike Air",
description: "Tennis court levitating sneaker",
img: "https://source.unsplash.com/user/erondu/PGTO_A0eLt4",
price: 100
},
{
categories: ["man"],
variants: ["black", "green", "yellow"],
sizes: [37, 39, 40, 42],
_id: "5f8edf08880a821cb8757d9b",
name: "Another Nike Air",
description: "Another description",
img: "https://source.unsplash.com/user/erondu/1600x900",
price: 120
}
];
const App = () => {
return (
<div className="App">
<Categories data={data} />
</div>
)
}
ReactDOM.render( <App /> , document.getElementById('root'))
img {
width: 100%;
max-width: 400px;
height: auto;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Here is an example with TypeScript
Upvotes: 2