Greg
Greg

Reputation: 256

How to populate select dropdown elements from API data?

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

Answers (1)

awran5
awran5

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

Edit laughing-hawking-q9ut6

Upvotes: 2

Related Questions