Я создала несколько радиокнопок с возможными ответами <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. **Логика выбора**: Теперь только одна радиокнопка может быть активной в любой момент времени, так как состояние управления происходит в родительском компоненте. С этими изменениями, выбранный элемент будет окрашен в зеленый цвет, а предыдущий выбор будет сбрасываться.
Если выбор сводится к да/нет, то почему должны быть две радиокнопки, а не один чекбокс? Но окей, вам виднее.
Складываем в массивы описания радиокнопок:
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} />
Всё .