【问题标题】:React Typescript - Working with multiple checkboxes in a listReact Typescript - 使用列表中的多个复选框
【发布时间】:2022-07-08 02:09:18
【问题描述】:

我有一个用例需要处理列表中的多个复选框

一次只能选择一个复选框

例如。如果我打开Checkbox 1 然后单击 Checkbox 2 - 那么我需要关闭 Checkbox 1 因为我打开on @ 987654325@

下面是我的代码

const ProductList = (props: InterdentalBrushProps) => {
  const [isChecked, setIsChecked] = useState(false);

  const { onEmit, brush_size, color_name, color_hex } = props;
  const handleClick = () => {
    setIsChecked(current => !current);
    onEmit({
      isChecked,
      onEmit,
    });
  };

  useEffect(() => {
    console.log('isChecked is: ', isChecked);
  }, [isChecked]);

  return (
    <List component="div" disablePadding>
      <ListItemButton className="product-outline" onClick={handleClick}>
        <CircleIcon sx={{ color: color_hex }} />
        <ListItemText sx={{ ml: 2 }} primary={brush_size} />
        <ListItemText sx={{ ml: -15 }} primary={color_name} />
        <Checkbox
          icon={<CircleIcon sx={{ color: '#ffffff' }} />}
          checkedIcon={<CheckCircleIcon />}
          checked={isChecked}
          color="primary"
          onChange={e => setIsChecked(e.target.checked)}
        />
      </ListItemButton>
    </List>
  );
};

export default ProductList;

父组件

const Products = (props: InterdentalBrushProps) => {
  const [open, setOpen] = useState(false);
  const handleClick = () => {
    setOpen(!open);
  };

  const { onEmit } = props;

  return (
    <List component="nav" aria-labelledby="nested-list-subheader">
      <ListItemButton
        disableRipple
        onClick={handleClick}
        style={{ backgroundColor: 'transparent' }}
      >
        <Orange />
        <ListItemText
          sx={{ ml: 2, mt: 3 }}
          primary={
            <Typography className="regular-20">
              Tepe Interdental Brush ™
            </Typography>
          }
        />
        {open ? (
          <ExpandLess className="icon-color" />
        ) : (
          <ExpandMore className="icon-color" />
        )}
      </ListItemButton>
      <Collapse
        className="product-scroll"
        in={open}
        timeout="auto"
        unmountOnExit
      >
        {open &&
          InterdentalBrush.regular.map((brush, index) => (
            <ProductsList
              onEmit={onEmit}
              key={index}
              brush_size={brush.brush_size}
              color_name={brush.color_name}
              color_hex={brush.color_hex}
            />
          ))}
      </Collapse>
    </List>
  );
};

export default Products;

我已经为上下文添加了父组件,希望可以修复。

请帮我解决这个问题

谢谢

【问题讨论】:

  • 标准是为此使用收音机,而不是复选框。这对可访问性更好。是否有充分的理由使用复选框?
  • 也就是说,这是一个带有一个复选框的组件。如果你有父母,那就是取消选中其余复选框的责任。
  • 单选按钮需要正确成对使用。所以我试图只有一个复选框
  • 如果你能帮我解决这个问题,我可以发布我的父组件
  • 不,同名的单选按钮是组的一部分,根据html standard。然后浏览器负责检查状态的排他性。但是,如果组件的拆分方式使其成为 PITA,请发布您的父母,我们可以看看。

标签: javascript reactjs typescript material-ui jsx


【解决方案1】:

好的,如果没有好的演示代码全部集中在一个位置或代码框,这有点难,所以这里有一个小得多的演示,它使用更小更简单的对象工作。如果您选中一个框,其余的将变为未选中。您可以看到我如何在子组件中绑定状态,并且父组件会相应地更新状态。您可以将其弹出到代码沙箱中,除了 react 和 typescript 之外没有其他依赖项。

import { useState } from "react";
import "./styles.css";

const AnimalArray = [
  {
    name: "Bear",
    selected: false
  },
  {
    name: "Cat",
    selected: false
  },
  {
    name: "Dog",
    selected: true
  }
];

type Animal = {
  name: string;
  selected: boolean;
};

type Animals = {
  animalList: Array<Animal>;
};

type AnimalProps = {
  animal: Animal;
  onSelectedChanged: (animal: Animal) => void;
};

const AnimalComponent = (props: AnimalProps) => {
  return (
    <div>
      <input type="text" value={props.animal.name} readOnly={true} />
      <input
        type="checkbox"
        checked={props.animal.selected}
        onChange={(el) => {
          props.onSelectedChanged({
            name: props.animal.name,
            selected: el.target.checked
          });
        }}
      />
    </div>
  );
};

const AnimalListComponent = (props: Animals) => {
  // this could be further pushed up state instead of (or in addition to) being handled here
  const [animals, setAnimals] = useState<Animal[]>(props.animalList);

  const onChange = (currentAnimal: Animal) => {
    setAnimals((currentState) =>
      currentState.map((i: Animal) =>
        i.name === currentAnimal.name
          ? {
              ...i,
              selected: currentAnimal.selected
            }
          : {
              ...i,
              selected: currentAnimal.selected ? false : i.selected
            }
      )
    );
  };

  return (
    <>
      <p>list</p>
      {animals.map((animal, index) => (
        <AnimalComponent
          key={index}
          onSelectedChanged={onChange}
          animal={animal}
        />
      ))}
    </>
  );
};

export default function App() {
  const [animals] = useState<Animals>({ animalList: AnimalArray });
  return (
    <div className="App">
      <AnimalListComponent animalList={animals.animalList} />
    </div>
  );
}

【讨论】:

    猜你喜欢
    • 2020-10-12
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2015-06-18
    相关资源
    最近更新 更多