reactjs - MUI 芯片作为可以选择的标签(类似复选框的行为)

标签 reactjs json typescript material-ui

我有一个 JSON 文件,我可以从中获取芯片的数据

[
    { "id": "4", "name": "Caucasian" },
    { "id": "5", "name": "Asian" },
    { "id": "6", "name": "Middle Eastern" },
    { "id": "7", "name": "Eurasian" },
    { "id": "8", "name": "African" },
    { "id": "10", "name": "Caribbean" },
    { "id": "11", "name": "Scandinavian European" },
    { "id": "12", "name": "Afro American" },
    { "id": "13", "name": "Latin American" },
    { "id": "14", "name": "European" },
    { "id": "15", "name": "Slavic European" },
    { "id": "16", "name": "American Indian" },
    { "id": "17", "name": "Inuit" },
    { "id": "21", "name": "Aboriginal/Torres Strait" },
    { "id": "22", "name": "Maori" },
    { "id": "23", "name": "Pacific Islander" },
    { "id": "24", "name": "Indian" },
    { "id": "26", "name": "Cambodian" },
    { "id": "27", "name": "Korean" },
    { "id": "28", "name": "Vietnamese" },
    { "id": "29", "name": "Thai" },
    { "id": "30", "name": "Chinese" },
    { "id": "31", "name": "Malaysian" },
    { "id": "32", "name": "Filipino" },
    { "id": "33", "name": "Japanese" },
    { "id": "34", "name": "Indonesian" },
    { "id": "35", "name": "Singaporean" },
    { "id": "147", "name": "Fijian" },
    { "id": "148", "name": "Tongan" },
    { "id": "150", "name": "Cook Islander" },
    { "id": "156", "name": "Northern European" },
    { "id": "157", "name": "Latin European" },
    { "id": "158", "name": "Central American" },
    { "id": "159", "name": "South American Indian" },
    { "id": "160", "name": "Hawaiian" },
    { "id": "161", "name": "East African" },
    { "id": "162", "name": "West African" },
    { "id": "163", "name": "Northern African" },
    { "id": "164", "name": "Eskimo" },
    { "id": "165", "name": "Arabic" },
    { "id": "166", "name": "Southern African" }
]

我已将这些数据映射为 MUI 芯片

{chipData.map((c) => (
    <Chip label={c.name} key={c.id} onClick={handleClick} />
))}

我需要做的是使每个芯片都可选择,然后将所有选定的芯片转移到与使用自动完成功能选择的芯片相匹配,并单击按钮。

所以基本上,有两种选择芯片的方法。

  1. 使用自动完成(键入并选择)
  2. 从显示所有筹码的模式中,能够像复选框一样选择它(单击并选择)

我尝试过使用useState,但问题是所有芯片都共享一个useState,因此每当选择/取消选择一个时,所有芯片都会跟随。

我有点被困在这里,但似乎无法找到与我想做的事情类似的解决方案。 任何见解/解决方案都会真正有帮助!

最佳答案

function Chip({name, onClick, variant, children}){
    return (
        <div className={variant} onClick={onClick}>{children}</div>
    )
}

const listOfChips = [
  { id: "4", name: "Caucasian" },
  { id: "5", name: "Asian" },
  { id: "6", name: "Middle Eastern" },
  { id: "7", name: "Eurasian" },
  { id: "8", name: "African" },
  { id: "10", name: "Caribbean" },
  { id: "11", name: "Scandinavian European" },
  { id: "12", name: "Afro American" },
  { id: "13", name: "Latin American" },
  { id: "14", name: "European" },
  { id: "15", name: "Slavic European" },
  { id: "16", name: "American Indian" },
  { id: "17", name: "Inuit" },
  { id: "21", name: "Aboriginal/Torres Strait" },
  { id: "22", name: "Maori" },
  { id: "23", name: "Pacific Islander" },
  { id: "24", name: "Indian" },
  { id: "26", name: "Cambodian" },
  { id: "27", name: "Korean" },
  { id: "28", name: "Vietnamese" },
  { id: "29", name: "Thai" },
  { id: "30", name: "Chinese" },
  { id: "31", name: "Malaysian" },
  { id: "32", name: "Filipino" },
  { id: "33", name: "Japanese" },
  { id: "34", name: "Indonesian" },
  { id: "35", name: "Singaporean" },
  { id: "147", name: "Fijian" },
  { id: "148", name: "Tongan" },
  { id: "150", name: "Cook Islander" },
  { id: "156", name: "Northern European" },
  { id: "157", name: "Latin European" },
  { id: "158", name: "Central American" },
  { id: "159", name: "South American Indian" },
  { id: "160", name: "Hawaiian" },
  { id: "161", name: "East African" },
  { id: "162", name: "West African" },
  { id: "163", name: "Northern African" },
  { id: "164", name: "Eskimo" },
  { id: "165", name: "Arabic" },
  { id: "166", name: "Southern African" },
];

function App() {
  const [allChips, setAllChips] = React.useState(listOfChips);
  const [selected, setSelected] = React.useState(new Set());

  function handleSelectionChanged(id) {
    // treat state as immutable
    // React only does a shallow comparison so we need a new Set
    const newSet = new Set(selected);
    if (newSet.has(id)) newSet.delete(id);
    else newSet.add(id);
    setSelected(newSet);
  }

  return (
    <React.Fragment>
      {allChips.map((c) => (
        <Chip
          key={c.id}
          onClick={() => handleSelectionChanged(c.id)}
          variant={selected.has(c.id) ? "filled" : "outlined"}
        >
          {c.name}
        </Chip>
      ))}
    </React.Fragment>
  );
}
ReactDOM.render(<App />, document.getElementById("root"));
div {
  border-radius: 20px;
  padding: 10px;
  margin: 10px;
}

.filled {
   background-color: black;
   color: white;
   border: 1px solid white;
}

.outlined {
   background-color: white;
   color: black;
   border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>

<div id="root"></div>

一种方法(还有其他方法)是使用一个 Set ,它保存所有已选择的 ID,并且根据 ID 是否在 Set 中,您可以执行一些条件操作渲染。

I have created a component chip here to show that it works you can of course use the MUI Chip and use the variant prop, or something else of course.

每当点击Chip时,您只需检查它是否在集合内。如果没有,请添加它。如果是,请将其删除。

就您在输入字段中的输入而言,该方法非常简单。您需要一个输入字段和 onChange 您需要通过 name 搜索可能的芯片,例如使用 startsWith() (或一些更高级的自动完成),一旦用户选择特定芯片,您将获得该芯片的 id 并可以调用 handleSelectionChanged(id) 使用该 ID。这当然意味着如果您输入两次,它将再次被删除,但您当然也可以更改此逻辑。

关于reactjs - MUI 芯片作为可以选择的标签(类似复选框的行为),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71926174/

相关文章:

javascript - 为什么通过 useContext 使用另一个钩子(Hook)值的自定义钩子(Hook)只显示其初始值?

json - 使用@JsonFormat 时的错误时间(+1 小时)

javascript - Typescript 数组推送,console.log 的奇怪行为

html - Bootstrap 3 : two button on a row

javascript - 如何在返回值之前等待其他事件完成?

javascript - 从单选按钮和复选框中选择的选项不传递数据

reactjs - 以动画背景作为加载器的 React-native 图像

javascript - Context API 中的 ReactJS 异步 axios

jQuery:计算输入中所有不同字符的出现次数并与 Json 数组进行比较

javascript - Angular 4 Json 对象到类对象