如何在使用钩子的反应中切换单选按钮的选中值?

时间:2020-03-10 17:48:02

标签: javascript reactjs react-hooks

按照下面的示例,我有一组根据某些外部数据构建的单选按钮。除了aria-checked属性以外,它们均按照我的期望进行渲染和工作。单击单选按钮可切换选中的值,但在选择另一个值后,它仍为true

如果我依次单击每个单选按钮,则会得到显示aria-checked="true"的单选按钮列表,这显然不是最佳体验。

我不确定在检查另一个按钮后如何将单选按钮的检查值切换回false。

任何帮助都会很棒!

输入:

    const [isChecked, setIsChecked] = useState(false);

    <Input
        type={type}
        id={id}
        value={id}
        name={name}
        aria-label={label}
        aria-checked={isChecked}
        onChange={() => setIsChecked(!isChecked)}
    />
    <Label htmlFor={id}>{label}</Label>

用法:

    <fieldset>
        {someData.map(item => {
            return (
                <RadioButton
                    type="radio"
                    key={item.id}
                    id={item.id}
                    name={item.name}
                    label={item.label}
                />
            );
        })}
    </fieldset>

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情。

const Radio = React.memo(function Radio({
  item,
  checked,
  onChange
}) {
  console.log("rendering", item.label);
  return (
    <label>
      {item.label}
      <input
        type="radio"
        value={item.id}
        checked={checked}
        onChange={onChange}
      />
    </label>
  );
});
const RadioList = ({ items, value, onChange }) => (
  <div>
    {items.map(item => (
      <Radio
        item={item}
        key={item.id}
        checked={item.id === value}
        onChange={onChange}
      />
    ))}
  </div>
);

const App = ({ items }) => {
  const [value, setValue] = React.useState(items[0].id);
  const [v, setV] = React.useState(items[1].id);
  const onChange = React.useCallback(
    e => setValue(e.target.value),
    []
  );
  const onOther = React.useCallback(
    e => setV(e.target.value),
    []
  );
  return (
    <div>
      <RadioList
        items={items}
        value={value}
        onChange={onChange}
      />
      <RadioList
        items={items}
        value={v}
        onChange={onOther}
      />
    </div>
  );
};
//render app
ReactDOM.render(
  <App
    items={[
      { id: "1", label: "one" },
      { id: "2", label: "two" },
      { id: "3", label: "three" },
      { id: "4", label: "four" }
    ]}
  />,
  document.getElementById("root")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

您应该在此处更改两件事。

  1. 在呈现同一组下的单选按钮列表时,所有单选按钮的name属性都应该相同。因此,不要从someData中读取name属性,而是将相同的name属性传递给每个按钮。或在每个对象的someData中保留相同的名称。

  2. 在那之后,我不认为状态应该在input组件上,因为一旦检查了单选按钮,即使单击某些单选按钮,也永远不会更改其值。您可以尝试在每个单选按钮上保持相同的名称属性。

因此解决方案可以是根据实际选择的无线电实际将选中的属性传递给Input组件。请检查以下代码:

const RadioButton = ({ type, id, name, label, checked, onChange }) => {
return (
    <>
        <input
            type={type}
            id={id}
            value={id}
            name={name}
            aria-label={label}
            aria-checked={checked}
            checked={checked}
            onChange={onChange}
        />
        <label htmlFor={id}>{label}</label>
    </>
)

}

const RadioGroup = () => {
const someData = [{
    id: 1,
    name: 'name',
    label: 'name 1'
}, {
    id: 2,
    name: 'name',
    label: 'name 2'
}, {
    id: 3,
    name: 'name',
    label: 'name 3'
}];

const [checkedValue, setIsChecked] = useState(1);

return (
    <fieldset>
        {someData.map(item => {
            return (
                <RadioButton
                    type="radio"
                    key={item.id}
                    id={item.id}
                    name="radioGroup"
                    label={item.label}
                    checked={checkedValue === item.id}
                    onChange={() => setIsChecked(item.id)}
                />
            );
        })}
    </fieldset>
)

}