React 에서 라디오버튼을 구현하기는 쉽습니다.
다만, 라디오버튼의 특성이랄까요? 한 번 선택한 값을 다시 해제하는 것이 어렵습니다.
이를 위해서 어떤 방식으로 라디오버튼 컴포넌트를 만들면, 이것을 해제 가능할지 알아보겠습니다.
import React, { useState, useEffect } from "react";
const SpecialRadio = ({ data, field_id, onValueChange, options }) => {
const [inputValue, setInputValue] = useState(
data && data[field_id] ? data[field_id] : ""
);
useEffect(() => {
if (data && data[field_id]) {
setInputValue(data[field_id]);
}
}, [data, field_id]);
const handleChange = (e) => {
const newValue = e.target.value;
setInputValue(newValue);
if (onValueChange) {
onValueChange(field_id, newValue);
}
};
if (!options) {
return null;
}
return (
{Object.entries(options).map(([key, value]) => (
))}
);
};
export default SpecialRadio;
조금 거창하게 SpecialRadio 라는 이름을 달아줬습니다.
해당 컴포넌트를 Form 형식의 하위 컴포넌트로 활용할 예정입니다.
data 라는 객체에는 각각의 field_id 가 key 로 그 field_id 에 해당하는 field_value 가 Value 로 담겨져 쌍을 이룰 겁니다.
onValueChange 를 통해서 하위 컴포넌트에서 값이 변경되어도, 상위 컴포넌트로 그 변경된 값이 data 내에 반영이 될 수 있도록 합니다.
중요한 건 options 가 되겠죠?
{0 : female, 1 : male }
options 는 이런 식으로 객체 형태로 받을 겁니다.
실제 화면에는 female 과 male이 나타날 겁니다.
그리고 누르면 0 이나 1로 실제 data 에는 담기게 되는 거죠.
이런 식으로 꾀하고 있습니다.
import React, { useState, useEffect } from "react";
const SpecialRadio = ({ data, field_id, onValueChange, options }) => {
const [inputValue, setInputValue] = useState(data[field_id] || "");
useEffect(() => {
setInputValue(data[field_id] || "");
}, [data, field_id]);
const handleToggle = (key) => {
const newValue = key === inputValue ? "" : key; // 현재 선택된 값과 같으면 빈 문자열로, 아니면 새 값으로 설정
setInputValue(newValue);
onValueChange(field_id, newValue);
};
return (
{Object.entries(options).map(([key, value]) => (
handleToggle(key)}
>
{value}
))}
);
};
export default SpecialRadio;
저는 위와 같이 변경을 했습니다.
기본적으로 <input type=”radio” … /> 를 사용하면 이미 클릭한 버튼을 다시 한 번 클릭하는 이벤트가 발생하지 않습니다.
때문에 div 형태로 라디오버튼 컴포넌트를 변경할 필요가 있습니다.
/* Special Radio 에 관한 설정 */
.special-design {
position: absolute; /* 절대 위치 설정 */
left: 0; /* 좌측에서 0px 떨어진 곳에 위치 */
top: 50%; /* 상단에서 50% 떨어진 곳에 위치 */
transform: translateY(-50%); /* Y축 기준 중앙 정렬 */
width: 22px;
height: 22px;
margin-top: 0.5rem;
border-radius: 100px;
margin-right: 10px; /* 디자인과 텍스트 사이의 간격 */
background: #ccc; /* 배경색 설정 */
}
.special-design::before {
content: ''; /* 초기 상태에서는 내용 없음 */
display: inline-block;
width: inherit;
height: inherit;
line-height: 22px;
text-align: center;
border-radius: inherit;
background: hsl(0, 0%, 90%);
font-size: 14px;
color: transparent; /* 체크 표시 색상을 숨김 */
transition: 0.1s;
}
.special-design.selected {
background: linear-gradient(to right bottom, hsl(330, 100%, 70%), hsl(330, 100%, 85%)); /* 배경을 다시 그리기 */
}
.special-design.selected::before {
content: '✔'; /* 선택 상태에서 체크 표시 */
color: white; /* 체크 표시의 색상 */
background: linear-gradient(to right bottom, hsl(330, 100%, 70%), hsl(330, 100%, 85%)); /* 배경을 다시 그리기 */
}
그리고 위처럼 CSS를 설정하여 예쁘게 해당 컴포넌트를 꾸며봤습니다.
실제로 라디오버튼의 모양을 하고 있습니다.
클릭하고 해제하는 것이 잘 되는 모습을 볼 수 있습니다.
이제 원하던 방식대로 동작하는 라디오버튼을 얻었습니다.