Имея следующий код html/css, который позволяет элементам html вести себя как радиогруппа:
.radios .radio{
background-color:#c5e043;
display:inline-block;
width:20px;
height:20px;
cursor:pointer
}
.radios input[type=radio]{
display:none
}
.radios input[type=radio]:checked + .radio{
background-color:#241009
}
<div class = "radios">
<div>
<input type = "radio" name = "rGroup" id = "r1" />
<label class = "radio" for = "r1"></label>
<input type = "radio" name = "rGroup" id = "r2" />
<label class = "radio" for = "r2"></label>
<input type = "radio" name = "rGroup" id = "r3" />
<label class = "radio" for = "r3"></label></div>
</div>
Я хочу написать в React некоторые стилизованные компоненты, которые ведут себя одинаково, но не знаю, как писать стилизованные компоненты input[type=radio] и .radios input[type=radio]:checked + .radio.
Вот код, кодовая песочница здесь. Он показывает элементы, но щелчок не работает, он не меняет выбранный элемент, как в приведенном выше коде.
Что следует изменить?
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
export const XSelectionBoxContainer = styled.div`
background-color: #c5e043;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
`;
export const Xlabel = styled.label`
background-color: #c5e043;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
`;
export const Xinput = styled.input`
display: none;
:checked {
background-color: #241009;
}
`;
function App() {
const options = [
{
label: "first",
value: "first",
name: "radio-group"
},
{
label: "second",
value: "second",
name: "radio-group"
},
{
label: "third",
value: "third",
name: "radio-group"
}
];
return (
<XSelectionBoxContainer>
{options.map((option) => {
return (
<div key = {option.label}>
<Xlabel htmlFor = {option.value}></Xlabel>
<Xinput
type = "radio"
name = {option.value}
value = "1"
id = {option.value}
/>
</div>
);
})}
</XSelectionBoxContainer>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Вам нужно поместить компонент label под элементом input, чтобы вы могли использовать оператор + в css для стилизации элемента метки, если input — это :checked.
Обновленный код ниже:
import React from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
export const XSelectionBoxContainer = styled.div`
background-color: #c5e043;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
`;
export const Xlabel = styled.label`
background-color: #c5e043;
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
`;
export const Xinput = styled.input`
display: none;
&:checked {
& + label {
background-color: #241009;
}
}
`;
function App() {
const options = [
{
label: "first",
value: "first",
name: "radio-group"
},
{
label: "second",
value: "second",
name: "radio-group"
},
{
label: "third",
value: "third",
name: "radio-group"
}
];
return (
<XSelectionBoxContainer>
{options.map((option) => {
return (
<div key = {option.label}>
<Xinput
type = "radio"
name = {option.name}
value = "1"
id = {option.value}
/>
<Xlabel htmlFor = {option.value}></Xlabel>
</div>
);
})}
</XSelectionBoxContainer>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
@LeoMessi, я обновил код. Xinput имеет атрибут имени, в котором вы передавали {option.value}. Измените его на {option.name}, чтобы сгруппировать.
Кажется, что они кликабельны, но не работают как радиогруппа, она должна иметь не более одной активной одновременно, как в примере html+css. вот песочница с вашим ответом: codeandbox.io/s/stoic-mopsa-t1cjzf?file=/src/index.js