如何在 React 中使用受控组件删除 :checked pseudo-class?
How to remove the :checked pseudo-class using a controlled component in React?
我有一个订阅选择组件,其中包含 3 个单独的 "plan" 组件。每个计划组件都包含一个用于选择该计划的单选按钮。因此,单选按钮没有组合在一起,而是实际上在 3 个组件中分开。
我目前能够在单击单选按钮时成功地"select" 每个计划。 "selected" 属性会针对每个计划组件进行相应更新,因此此功能可以正常工作。问题是每个单选按钮在视觉上都保持 "selected" 因为样式是通过 :checked 伪 class 应用的,当单击另一个按钮时它似乎没有得到更新。
换句话说,我点击按钮 1 -> 按钮 1 被选中,计划 1 被选中,计划 1 的边框颜色发生变化。我单击按钮 2 -> 选择按钮 2,选择计划 2,计划 2 的边框颜色发生变化,不再选择计划 1,计划 1 的边框颜色恢复正常,但计划 1 的按钮仍处于选中状态。
SubscriptionsContainer.js
const SubscriptionsContainer = (props) => {
const [selected, setSelected] = useState('2');
const plansList = [
{
...plan info
}
]
const selectPlan = (e) => {
setSelected(e.target.value);
}
const plansComponents = plansList.map(plan => (
<SubscriptionPlan
key={plan.id}
id={plan.id}
title={plan.title}
price={plan.price}
feature1={plan.feature1}
feature2={plan.feature2}
feature3={plan.feature3}
feature4={plan.feature4}
selected={plan.id === selected}
selectPlan={selectPlan}
/>
));
return (
<FlexContainer>
{plansComponents}
</FlexContainer>
)
}
SubscriptionPlan.js
const SubscriptionPlan = ({
selected,
id,
title,
price,
feature1,
feature2,
feature3,
feature4,
selectPlan,
...props
}) => {
return (
<PlanContainer selected={selected} flexDirection="column">
<h3>{title}</h3>
<P>{price}/mo</P>
<P>{feature1}</P>
<P>{feature2}</P>
<P>{feature3}</P>
<P>{feature4}</P>
<RadioInput onChange={selectPlan} selected={selected} name={id} value={id} />
</PlanContainer>
)
};
RadioInput.js
const RadioInput = (props) => {
console.log(props.selected);
return (
<Item>
<RadioButton
type="radio"
value={props.value}
selected={props.selected}
onChange={props.onChange}
{...props} />
<RadioButtonStyle/>
<RadioButtonLabel>{props.value}</RadioButtonLabel>
</Item>
)
}
const Item = styled.div`
display: flex;
align-items: center;
height: 48px;
position: relative;
`;
const RadioButtonStyle = styled.label`
position: absolute;
top: 33%;
width: 16px;
height: 16px;
border-radius: 50%;
background: white;
border: 1px solid ${colors.primary500};
`;
const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 16px;
height: 16px;
margin-right: 10px;
&:hover {
cursor: pointer;
}
&:hover ~ ${RadioButtonStyle} {
background: ${colors.secondary500};
opacity: 0.5;
border: 1px solid ${colors.secondary600};
&::after {
content: "";
display: block;
border-radius: 50%;
width: 8px;
height: 8px;
margin: 4px;
background: white;
}
}
&:focus + ${RadioButtonStyle} {
border: 1px solid ${colors.secondary600};
}
&:checked + ${RadioButtonStyle} {
background: ${colors.secondary500};
opacity: 1;
border: 1px solid ${colors.secondary600};
&::after {
content: "";
display: block;
border-radius: 50%;
width: 8px;
height: 8px;
margin: 4px;
box-shadow: 1px 3px 3px 1px rgba(0, 0, 0, 0.1);
background: white;
}
}
`;
const RadioButtonLabel = styled.div`
color: ${colors.primary800};
`
您可以通过为所有输入赋予相同的名称来分组,例如 name="subscriptionType"
,即使它们位于不同的组件中也是如此。
希望有帮助
尝试用 "checked" 替换复选框组件上的 "value" 道具。
const RadioInput = (props) => {
console.log(props.selected);
return (
<Item>
<RadioButton
type="radio"
// value={props.value} <-- removed
checked={props.value} // <-- added
selected={props.selected}
onChange={props.onChange}
{...props} />
<RadioButtonStyle/>
<RadioButtonLabel>{props.value}</RadioButtonLabel>
</Item>
)
}
查看可能重复的问题:
我有一个订阅选择组件,其中包含 3 个单独的 "plan" 组件。每个计划组件都包含一个用于选择该计划的单选按钮。因此,单选按钮没有组合在一起,而是实际上在 3 个组件中分开。
我目前能够在单击单选按钮时成功地"select" 每个计划。 "selected" 属性会针对每个计划组件进行相应更新,因此此功能可以正常工作。问题是每个单选按钮在视觉上都保持 "selected" 因为样式是通过 :checked 伪 class 应用的,当单击另一个按钮时它似乎没有得到更新。
换句话说,我点击按钮 1 -> 按钮 1 被选中,计划 1 被选中,计划 1 的边框颜色发生变化。我单击按钮 2 -> 选择按钮 2,选择计划 2,计划 2 的边框颜色发生变化,不再选择计划 1,计划 1 的边框颜色恢复正常,但计划 1 的按钮仍处于选中状态。
SubscriptionsContainer.js
const SubscriptionsContainer = (props) => {
const [selected, setSelected] = useState('2');
const plansList = [
{
...plan info
}
]
const selectPlan = (e) => {
setSelected(e.target.value);
}
const plansComponents = plansList.map(plan => (
<SubscriptionPlan
key={plan.id}
id={plan.id}
title={plan.title}
price={plan.price}
feature1={plan.feature1}
feature2={plan.feature2}
feature3={plan.feature3}
feature4={plan.feature4}
selected={plan.id === selected}
selectPlan={selectPlan}
/>
));
return (
<FlexContainer>
{plansComponents}
</FlexContainer>
)
}
SubscriptionPlan.js
const SubscriptionPlan = ({
selected,
id,
title,
price,
feature1,
feature2,
feature3,
feature4,
selectPlan,
...props
}) => {
return (
<PlanContainer selected={selected} flexDirection="column">
<h3>{title}</h3>
<P>{price}/mo</P>
<P>{feature1}</P>
<P>{feature2}</P>
<P>{feature3}</P>
<P>{feature4}</P>
<RadioInput onChange={selectPlan} selected={selected} name={id} value={id} />
</PlanContainer>
)
};
RadioInput.js
const RadioInput = (props) => {
console.log(props.selected);
return (
<Item>
<RadioButton
type="radio"
value={props.value}
selected={props.selected}
onChange={props.onChange}
{...props} />
<RadioButtonStyle/>
<RadioButtonLabel>{props.value}</RadioButtonLabel>
</Item>
)
}
const Item = styled.div`
display: flex;
align-items: center;
height: 48px;
position: relative;
`;
const RadioButtonStyle = styled.label`
position: absolute;
top: 33%;
width: 16px;
height: 16px;
border-radius: 50%;
background: white;
border: 1px solid ${colors.primary500};
`;
const RadioButton = styled.input`
opacity: 0;
z-index: 1;
border-radius: 50%;
width: 16px;
height: 16px;
margin-right: 10px;
&:hover {
cursor: pointer;
}
&:hover ~ ${RadioButtonStyle} {
background: ${colors.secondary500};
opacity: 0.5;
border: 1px solid ${colors.secondary600};
&::after {
content: "";
display: block;
border-radius: 50%;
width: 8px;
height: 8px;
margin: 4px;
background: white;
}
}
&:focus + ${RadioButtonStyle} {
border: 1px solid ${colors.secondary600};
}
&:checked + ${RadioButtonStyle} {
background: ${colors.secondary500};
opacity: 1;
border: 1px solid ${colors.secondary600};
&::after {
content: "";
display: block;
border-radius: 50%;
width: 8px;
height: 8px;
margin: 4px;
box-shadow: 1px 3px 3px 1px rgba(0, 0, 0, 0.1);
background: white;
}
}
`;
const RadioButtonLabel = styled.div`
color: ${colors.primary800};
`
您可以通过为所有输入赋予相同的名称来分组,例如 name="subscriptionType"
,即使它们位于不同的组件中也是如此。
希望有帮助
尝试用 "checked" 替换复选框组件上的 "value" 道具。
const RadioInput = (props) => {
console.log(props.selected);
return (
<Item>
<RadioButton
type="radio"
// value={props.value} <-- removed
checked={props.value} // <-- added
selected={props.selected}
onChange={props.onChange}
{...props} />
<RadioButtonStyle/>
<RadioButtonLabel>{props.value}</RadioButtonLabel>
</Item>
)
}
查看可能重复的问题: