Как можно назначить класс для выбранного элемента input-radio в React.js?

Я создала несколько радиокнопок с возможными ответами <i>да/нет</i>. Мне нужно, чтобы при выборе одного из вариантов цвет выбранного ответа изменялся на зелёный. У меня уже есть работающий код, но есть проблема: если пользователь выберет <i>да</i>, а затем передумает и выберет <i>нет</i>, то <i>да</i> остается зелёным, а <i>нет</i> также становится зелёным. При повторном выборе <i>да</i> этот вариант ответа перестает быть зелёным, и так далее по кругу. <br/> Я понимаю, почему это происходит в моем коде, но не знаю, как это исправить. Можете помочь? <br/><br/> Вот мой код: <br/><b>Radio.jsx - файл:</b> <br/><pre><code class="javascript">import { useState } from "react"

export default function Radio({ id, name, children }) {

  const [isActive, setIsActive] = useState(false);

  function SelectValue() {
    setIsActive(!isActive)
  }

  // Если инпут активный, то к его лэйблу привязывается стиль

  return (
    &lt;&gt;
      &lt;label
        className={isActive ? 'activeBox' : ''} 
        &gt;
        &lt;input 
          onChange={SelectValue}
          type='radio'
          id={id}
          name={name}
        /&gt;
        {children}
      &lt;/label&gt;
    &lt;&gt;
  )
}</code></pre> <br/><br/><b>Form.jsx - файл:</b> <br/><pre><code class="javascript">import Radio from "./Radio";

export default function Form() {
return (
    &lt;form className="form" action="url" method='post'&gt;
      &lt;div className="form__presence"&gt;
        &lt;label&gt;Подтвердите присутствие&lt;/label&gt;
        &lt;span&gt;
          &lt;Radio id="coming" name="presence"&gt;Я приду&lt;/Radio&gt;
          &lt;Radio id="notComing" name="presence"&gt;Я не приду&lt;/Radio&gt;
          …     
        &lt;/span&gt;
      &lt;/div&gt;
    &lt;/form&gt;
  )
} </code></pre>
  • 22 января 2025 г. 12:44
Ответы на вопрос 2
Чтобы исправить проблему с выделением выбранной радиокнопки (radio button) и сделать так, чтобы только выбранный вариант имел зеленый цвет, вам нужно управлять состоянием выбора в родительском компоненте (`Form`) и передавать это состояние в дочерние компоненты (`Radio`). Вот как это можно сделать:

### Изменение файла Radio.jsx:

Вместо хранения состояния `isActive` в компоненте `Radio`, вы можете передавать информацию о выборе через пропсы. Добавьте пропс `isSelected`, который будет определять, является ли данный элемент активным, и `onSelect` для обработки изменения выбора:

```javascript
import { useState } from "react";

export default function Radio({ id, name, isSelected, onSelect, children }) {
  return (
    <>
      <label className={isSelected ? 'activeBox' : ''}>
        <input
          type="radio"
          id={id}
          name={name}
          onChange={() => onSelect(id)} // Передаем id при изменении
        />
        {children}
      </label>
    </>
  );
}
```

### Изменение файла Form.jsx:

Теперь вам нужно управлять состоянием выбора в компоненте `Form`. Добавьте состояние для выбранного элемента и передайте соответствующие пропсы каждому `Radio`:

```javascript
import { useState } from "react";
import Radio from "./Radio";

export default function Form() {
  const [selectedValue, setSelectedValue] = useState(null); // состояние для хранения выбранного значения

  function handleSelect(value) {
    setSelectedValue(value); // обновляем выбранное значение
  }

  return (
    <form className="form" action="url" method='post'>
      <div className="form__presence">
        <label>Подтвердите присутствие</label>
        <span>
          <Radio 
            id="coming" 
            name="presence" 
            isSelected={selectedValue === 'coming'} 
            onSelect={handleSelect}
          >
            Я приду
          </Radio>
          <Radio 
            id="notComing" 
            name="presence" 
            isSelected={selectedValue === 'notComing'} 
            onSelect={handleSelect}
          >
            Я не приду
          </Radio>
        </span>
      </div>
    </form>
  );
}
```

### Объяснение:

1. **Состояние в `Form`**: Мы храним выбранное значение в состоянии `selectedValue`. Это состояние будет обновляться при выборе радиокнопки.

2. **Передача пропсов**: Мы передаем `isSelected` (true/false) и `onSelect` (функцию для обновления состояния) в дочерний компонент `Radio`. Проп `isSelected` сообщает, является ли текущая кнопка активной, а `onSelect` вызывается при изменении состояния.

3. **Логика выбора**: Теперь только одна радиокнопка может быть активной в любой момент времени, так как состояние управления происходит в родительском компоненте.

С этими изменениями, выбранный элемент будет окрашен в зеленый цвет, а предыдущий выбор будет сбрасываться.
Если выбор сводится к да/нет, то почему должны быть две радиокнопки, а не один чекбокс? Но окей, вам виднее. 

Складываем в массивы описания радиокнопок:

const presence = [
  { value:    'coming', text:    'Приду' },
  { value: 'notComing', text: 'Не приду' },
];

const transport = [
  { value: 'yes', text:  'Да' },
  { value:  'no', text: 'Нет' },
];

Создаём стейт с данными формы и метод его обновления:

const [ formData, setFormData ] = useState({});
const onChange = ({ target: t }) =>
  setFormData(fd => ({
    ...fd,
    [t.name]: t.value,
  }));

Создаём компонент радиогруппы:

const RadioGroup = ({ title, name, items, value, onChange }) => (
  <div className="radiogroup">
    <div className="radiogroup-title">{title}</div>
    {items.map(n => (
      <div key={n.value} className="radiogroup-item">
        <label className={value === n.value ? 'radiogroup-item-active' : ''}>
          <input
            type="radio"
            name={name}
            value={n.value}
            onChange={onChange}
          />
          {n.text}
        </label>
      </div>
    ))}
  </div>
);

Создаём его экземпляры:

<RadioGroup
  title="Подтвердите присутствие"
  name="presence"
  items={presence}
  value={formData.presence}
  onChange={onChange}
/>
<RadioGroup
  title="Нужен ли трансфер до места проведения?"
  name="transport"
  items={transport}
  value={formData.transport}
  onChange={onChange}
/>

Всё .
Похожие вопросы