다중 Check List 메뉴
미리 체크리스트를 주고, 원하는 만큼 골라서 추가할 수 있는 리스트픽 컴포넌트가 필요합니다.
트위터 활동은 동시에 다양하게 할 수 있기 때문에, 하나를 체크했다고 다른 체크가 풀리는 게 아니라, 다중으로 체크가 되어야 합니다.
지금부터 다중 체크리스트 컴포넌트를 제작하겠습니다.
CheckList 컴포넌트
<Checklist
placeholder="트위터 활동"
elements={["RT", "마음", "일상/글", "그림", "구독"]}
onChecked={(e) => setXType(e)}
/>
CheckList 컴포넌트를 페이지로 호출하면, 위와 같은 DOM이 출력됩니다.
CheckList 소스코드
import { FormTextContainer, FormText, ChecklistText } from "@/styles/Texts";
import {
CheckboxInput,
CheckboxLabel,
ChecklistSpacer,
} from "@/styles/CheckBox";
import { ChecklistContainer } from "@/styles/Containers";
import React, { useState } from "react";
export default function Checklist(props) {
const { elements = [1, 2, 3], onChecked, placeholder } = props;
const [checkedList, setCheckedList] = useState(
new Array(elements.length).fill(false)
);
const handleChange = (e, idx) => {
const { checked } = e.target;
const newCheckedList = [...checkedList];
newCheckedList[idx] = checked;
setCheckedList(newCheckedList);
let newStr = "";
elements.forEach((e, idx) => {
if (newCheckedList[idx] === true) {
newStr += e + " | ";
}
});
onChecked(newStr.slice(0, -3));
};
return (
<ChecklistContainer>
<FormTextContainer>
<FormText>{placeholder}</FormText>
</FormTextContainer>
<ChecklistSpacer />
{elements.map((element, idx) => (
<CheckboxLabel key={idx}>
<CheckboxInput
type="checkbox"
checked={checkedList[idx]}
onChange={(e) => handleChange(e, idx)}
/>
<ChecklistText>{element}</ChecklistText>
</CheckboxLabel>
))}
</ChecklistContainer>
);
}
props 설정
const { elements, onChecked, placeholder } = props;
부모 컴포넌트로부터 3가지 props를 전달받습니다.
elements : 체크리스트 항목으로 구성된 배열입니다.
onChecked : 선택된 체크박스 정보가 담긴 state를 상위 컴포넌트에 전달하는 콜백 함수입니다.
placeholder : 체크리스트 상단에 나타나는 설명 텍스트입니다.
State 설정
const [checkedList, setCheckedList] = useState(
new Array(elements.length).fill(false)
);
checkedList State는 각 항목의 선택 여부를 추적하는 Array입니다.
초기값은 new Array(elements.length).fill(false)로, 모든 체크박스가 선택되지 않은 상태로 시작합니다.
핸들러 함수 : handleChange
const handleChange = (e, idx) => {
const { checked } = e.target;
const newCheckedList = [...checkedList];
newCheckedList[idx] = checked;
setCheckedList(newCheckedList);
let newStr = "";
elements.forEach((e, idx) => {
if (newCheckedList[idx] === true) {
newStr += e + " | ";
}
});
onChecked(newStr.slice(0, -3));
};
체크박스를 클릭할 때 호출되는 콜백함수입니다.
1. e.target.checked로 현재 체크박스의 boolean 상태를 확인합니다. (체크되면 true, 해제되면 false)
2. 기존 checkedList를 깊은 복사(newCheckedList)한 후, 체크/체크해제된 값만 변경하고, setCheckedList로 상태를 업데이트합니다.
3. 체크리스트 정보가 담긴 elements를 forEach()문으로 순회합니다.
만약 해당 순서의 newCheckedList값이 true일 경우, newStr이라는 String 변수에 해당 element(e)를 추가합니다.
선택된 항목은 " | "로 구분되며 마지막 구분자는 slice(0, -3)을 이용해서 제거됩니다.
4. 조합된 문자열인 newStr을 onChecked 함수에 전달해서, 상위 컴포넌트에 전달합니다.
JSX 분석
<ChecklistContainer>
<FormTextContainer>
<FormText>{placeholder}</FormText>
</FormTextContainer>
<ChecklistSpacer />
{elements.map((element, idx) => (
<CheckboxLabel key={idx}>
<CheckboxInput
type="checkbox"
checked={checkedList[idx]}
onChange={(e) => handleChange(e, idx)}
/>
<ChecklistText>{element}</ChecklistText>
</CheckboxLabel>
))}
</ChecklistContainer>
ChecklistContainer : 전체 컴포넌트를 감싸는 컨테이너입니다.
FormTextContainer와 FormText : 설명 텍스트(placeholder)를 표시합니다.
ChecklistSpacer : 텍스트(FormText)와 체크리스트 사이의 간격을 만듭니다.
체크박스 리스트 : elements 배열을 map으로 순회하여 각각의 체크박스와 레이블을 생성합니다.
CheckboxInput : 체크박스를 표시하며, 체크 여부도 확인할 수 있습니다.
ChecklistText : 해당 체크박스가 어떤 내용인지를 설명하는 텍스트입니다.
Styled-Components
ChecklistContainer, FormText, FormTextContainer, ChecklistSpacer, CheckboxInput, ChecklistText 모두 특별한 기능이 추가된 컴포넌트가 아니라, styled-components로 스타일만 입힌 컴포넌트입니다.
스타일 컴포넌트의 코드 전문을 보고 싶으면, 접은 글을 펼치세요.
const ChecklistContainer = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
width: 300px;
margin-left: 2em;
margin-top: 1em;
margin-bottom: 2em;
/* background-color: pink; */
`;
const FormTextContainer = styled.div`
display: flex;
flex: 1;
justify-content: center;
`;
const FormText = styled.text`
font-size: 19px;
font-weight: bold;
`;
const ChecklistSpacer = styled.div`
height: 10px;
`;
const CheckboxLabel = styled.label`
display: flex;
align-items: center;
margin-bottom: 6px;
cursor: pointer;
/* background-color: blue; */
`;
const CheckboxInput = styled.input`
display: flex;
justify-content: center;
align-items: center;
appearance: none; // 기본 체크박스 스타일 제거
margin-left: 0px; // 기본으로 설정된 마진 제거
margin-right: 10px;
width: 20px;
height: 20px;
cursor: pointer;
background-color: #efecec;
border-radius: 2px;
border: none; // 테두리 색도 파란색으로
// 체크박스가 선택되었을 때의 스타일
&:checked {
background-color: blue; // 배경색을 파란색으로
/* border: 2px solid blue; // 테두리 색도 파란색으로 */
}
&:checked:after {
content: "✔"; // 체크 표시를 추가
color: white;
display: block;
text-align: center;
font-size: 18px;
}
`;
작동 구조
원하는 걸 선택한 만큼, X친소 표에 모든 내용이 담깁니다.
'개발일지 > 트친소 생성기 사이트' 카테고리의 다른 글
[원신 X친소표 사이트 제작기] 4. Dropdown 리스트픽 만들기 #React (0) | 2024.12.04 |
---|---|
[원신 X친소표 사이트 제작기] 3. 한 줄/여러 줄 TextInput 만들기 #React (0) | 2024.11.30 |
[원신 X친소표 사이트 제작기] 2. 이미지를 불러오기/미리보기 구현 #React (0) | 2024.11.28 |
[원신 X친소표 사이트 제작기] 1. 제작한 이유와 반응 살펴보기 (1) | 2024.11.27 |
원신 트친소 생성기 제작 및 이용방법 (2) | 2024.10.19 |