【问题标题】:How to populate select dropdown elements from API data?如何从 API 数据中填充选择下拉元素?
【发布时间】:2021-03-03 08:49:25
【问题描述】:

我正在学习 React,我正在尝试创建一个动态的下拉选择。我正在从另一个组件中成功导入从 API 获取的数据。我想从 fetched data 中按 category 填充 select option,它是单个字符串的 array “女人”、“男人”或“孩子”。我想要的是,最初列出所有数据,为 category 字符串提供 3 个 options,并根据 仅列出匹配的 products >onChange 事件。 现在,当我单击 select 时,整个应用程序都会呈现并且看不到错误。
任何帮助将不胜感激

API 数据如下所示:

[
  {
    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
  }
]

类别组件

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

【问题讨论】:

  • 请不要使用console.log 输出。发布实际上可复制/可用的内容。
  • @Yoshi 感谢您的指出。我更新了问题
  • 感谢您的更新,但是与之前的 console.log 输出相比,图像如何可复制/可用?如果您希望人们帮助您,请让他们轻松地帮助您。没有人愿意为了让原型运行而输入示例数据。
  • 嘿 @ Yoshi 我试图准确地说,但是,是的,你说得对。那么,你能帮我解决这个问题吗?为了更准确和更容易为社区提供帮助,这里缺少什么?
  • 一般来说,一个好的阅读是How to create a Minimal, Reproducible Example。然后对于您的问题,将该图像中显示的数据发布为 JSON 或有效的 javascript 数据结构。这样人们就可以复制了。

标签: reactjs


【解决方案1】:

试试这样的:

// 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>

这是一个使用 TypeScript 的示例

【讨论】:

  • 感谢您的回答和您的努力。我试图运行您在代码沙箱中提供的代码。但是在第一个 useState 有一个错误。它说 'TypeError: Cannot read property 'categories' of undefined ' 。我想如果我们解决这个问题,应用程序就会运行。提前致谢
  • 您是否使用了另一个沙箱或链接above 的沙箱?根据您的代码,我假设您使用的 TypeScript 已经定义了数据数组。在没有 TypeScript 的情况下检查这个 sandbox,我只是硬编码了初始状态。
  • 看起来不错。我用打字稿检查了链接。我可以解决将初始值放在引号中的错误。但我的问题是,“数据”道具是我已经在“ui”中列出的主要数据,并且只想根据选择输出“ui”中的数据。所以我们不需要输出任何东西,我们必须根据将要选择的类别显示已经创建和样式化的数据。
  • 对不起,我没有完全正确。您的意思是您最初不需要显示任何数据并仅在选择时显示它?如果是这样,只需删除selected 状态并将useEffet 逻辑移动到handleSelcet 函数。检查这个sandbox
  • 抱歉不准确。我已经在“ui”中列出了数据,最初我想保留在“ui”中列出的所有数据,并且根据选项选择,仅显示与类别匹配的产品。
猜你喜欢
  • 2019-10-05
  • 1970-01-01
  • 2013-04-05
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多