Я создала несколько радиокнопок с возможными ответами <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 (
<>
<label
className={isActive ? 'activeBox' : ''}
>
<input
onChange={SelectValue}
type='radio'
id={id}
name={name}
/>
{children}
</label>
<>
)
}</code></pre> <br/><br/><b>Form.jsx - файл:</b> <br/><pre><code class="javascript">import Radio from "./Radio";
export default function Form() {
return (
<form className="form" action="url" method='post'>
<div className="form__presence">
<label>Подтвердите присутствие</label>
<span>
<Radio id="coming" name="presence">Я приду</Radio>
<Radio id="notComing" name="presence">Я не приду</Radio>
…
</span>
</div>
</form>
)
} </code></pre>
Чтобы исправить проблему с выделением выбранной радиокнопки (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. **Логика выбора**: Теперь только одна радиокнопка может быть активной в любой момент времени, так как состояние управления происходит в родительском компоненте.
С этими изменениями, выбранный элемент будет окрашен в зеленый цвет, а предыдущий выбор будет сбрасываться.
Если выбор сводится к да/нет, то почему должны быть две радиокнопки, а не один чекбокс? Но окей, вам виднее. <br/> <br/> Складываем в массивы описания радиокнопок: <br/> <br/> <pre><code class="javascript">const presence = [
{ value: 'coming', text: 'Приду' },
{ value: 'notComing', text: 'Не приду' },
];
const transport = [
{ value: 'yes', text: 'Да' },
{ value: 'no', text: 'Нет' },
];</code></pre> <br/> Создаём стейт с данными формы и метод его обновления: <br/> <br/> <pre><code class="javascript">const [ formData, setFormData ] = useState({});
const onChange = ({ target: t }) =>
setFormData(fd => ({
...fd,
[t.name]: t.value,
}));</code></pre> <br/> Создаём компонент радиогруппы: <br/> <br/> <pre><code class="javascript">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>
);</code></pre> <br/> Создаём его экземпляры: <br/> <br/> <pre><code class="html"><RadioGroup
title="Подтвердите присутствие"
name="presence"
items={presence}
value={formData.presence}
onChange={onChange}
/>
<RadioGroup
title="Нужен ли трансфер до места проведения?"
name="transport"
items={transport}
value={formData.transport}
onChange={onChange}
/></code></pre> <br/> <a href="https://jsfiddle.net/7bgefph2/1/" rel="nofollow">Всё</a> .